info@yenlo.com
ned
Menu
WSO2 Enterprise Integrator 11 min

Foutafhandeling in WSO2 Enterprise Integrator

Rob Blaauboer
Rob Blaauboer
Integration Consultant & WSO2 Trainer
Error Handling WSO2 Enterprise Integrator

In de ideale wereld bestaan er geen problemen en geen foutmeldingen. Helaas leven we in een reële wereld, waar niet altijd alles zo gaat als we gehoopt of gepland hadden. Het belangrijkste deel van de WSO2 Enterprise Integrator waarbij we met foutmeldingen te maken krijgen zijn de proxies en de API’s. De foutafhandeling voor jouw services en API’s is essentieel voor een goede ervaring als ontwikkelaar. Er zijn maar weinig dingen die nog irritanter zijn dan een onduidelijke foutmelding met ‘Er is iets fout gegaan’. Een gedegen foutafhandeling is er niet alleen voor anderen, maar vooral ook voor jezelf. Een half jaar na publicatie zul je jezelf dankbaar zijn dat je foutmelding krijgt met een bericht zoals ‘Verbinding maken met FinanceWorld Invoicing service mislukt vanwege een verbindingstimeout’ in plaats van ‘Er is iets fout gegaan’. 

In deze blog ga ik het hebben over foutafhandeling en de manier waarop we dat kunnen instellen in de WSO2 Enterprise Integrator.

Mechanismen voor foutafhandeling

Sommige fouten ontstaan buiten een verwerking. Als je bijvoorbeeld de Enterprise Integrator twee keer probeert op te starten, dan zou je een stack trace kunnen krijgen die aangeeft dat een bepaald bestand vergrendeld is. 

Error Handling WSO2 Enterprise Integrator 1

Een andere foutmelding, zoals de ‘out of memory’, kan de volledige Java Virtual Machine platleggen. Daar kun je opnieuw weinig anders aan doen dan de hoeveelheid geheugen vergroten en/of andere programma’s die tegelijkertijd draaien stopzetten.

Waar ik het nu over heb, is de foutafhandeling met betrekking tot de integratieprocessen en de fouten die veroorzaakt worden door een eindpunten, de inhoud van berichten en dergelijke.

De Fault Sequence in de Integration Studio 

Als je een proxy of API aanmaakt en je daarbij de nieuwe designscherm in de Integration Studio gebruikt, heb je wellicht het rode driehoekje al gezien. Dit is de ‘fault sequence’. De fault sequence wordt uitgevoerd als er een FOUT in een EI-component optreed, niet te verwarren met een fout die teruggegeven wordt door de back-end. Fouten die bij de back-end vandaan komen, worden afgehandeld in de inSequence of de outSequence en worden (‘by default’) niet doorgestuurd naar de fault sequence!

Error Handling WSO2 Enterprise Integrator 2

Dus een van de dingen die we op willen pikken, is als er een eindpunt niet beschikbaar is. Om dat te laten zien heb ik een eindpunt gemaakt dat verwijst naar de echo service die in de Enterprise Integrator ingebouwd zit. Ik zet het eindpunt uit. Zodat ik, idealiter, een foutmelding krijg. Ik heb bovendien de configuratie van de standaard ‘fault’ sequence gekopieerd en een aantal wijzigingen aangebracht. Daardoor is het duidelijk dat de informatie die naar de console gepusht wordt vanuit de door mij gecreëerde, aangepaste fault sequence komt.

<?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

Dit is de respons in de console:

[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>

Het is een stuk beter dan helemaal geen bericht, maar er is nog een lange weg te gaan. We hebben ook een reactie in onze client.

Error Handling WSO2 Enterprise Integrator 3

Laten we het in de volgende paragraaf in een sequence zetten.

Een generieke Error sequence maken

Er is een betere aanpak! En de aanpak die we hebben moet beter voor een gedegen foutafhandeling. Dezelfde foutafhandeling kan namelijk volledig naar een sequence omgezet worden. Wat we hierbij moeten opnemen zijn dingen die ons helpen om vast te stellen wat er mis is gegaan. Je kunt denken aan elementen zoals:

  • uuid (unieke ID per bericht)
  • datetime (de tijdsaanduiding wanneer de fout plaatsvond)
  • eigen foutcodes (vertalen van WSO2 codes naar je eigen codes)

Bovendien zullen we ook een bericht terug moeten sturen naar de client waarin we aangeven dat er iets mis is gegaan. Fouten die niet technisch zijn (zie de alinea ‘Een lege respons’ later in deze blog) zouden ook opgenomen moeten worden, zodat er één error sequence is die aangeroepen wordt.

Foutmeldingen in een sequence

Als je een sequence definieert, kun je daarbij ook de ‘on-error sequence’ bepalen die daarmee geassocieerd wordt. Als er dan iets mis gaat in een sequence (als je bijvoorbeeld een eindpunt aanroept), dan kun je nog steeds een foutmelding krijgen en die netjes afhandelen. Dus, in plaats van een proxy waarmee de foutmelding getriggerd wordt, ga ik een proxy maken die de sequence in gang zet als het aangeroepen eindpunt uitgeschakeld is. We gebruiken hetzelfde eindpunt als wat we eerder hadden. In dit geval zouden we dezelfde foutmelding moeten krijgen. Maar ik breng opnieuw een wijziging aan in de error sequence om aan te geven dat we niet te maken hebben met de fault sequence die op proxy betrekking heeft. Dit is de fault sequence die gemaakt en geassocieerd is met de sequence die we alleen aanroepen.

<?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>

De bovenstaande sequence kan aangepast worden om ook naar een algemene error sequence te verwijzen.

Error Proxy2

Een tweede proxy roept de sequence aan en geeft een respons. 

<?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>

Zelfs als ik de sequence opneem in de fault sequence van de proxy, zal het nog steeds de ‘sequence fault’ aanroepen, omdat de fout daar ontstond.

[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 het eindpunt en er wordt een foutcode 101504 gegeven (“Connection timed out (no input was detected on this connection over the maximum period of inactivity)”).

<?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>

Zoals je in de respons kunt zien, krijg ik nu een aantal log mediators die aangeven met welke fout we te maken hebben. De generieke sequence zou de WSO2 foutcodes moeten vertalen naar een set persoonlijke foutcodes, zoals ‘EP_001- Eindpunt niet beschikbaar’ of iets dergelijks.

Een lege respons

Maar wat is er aan de hand als we een lege respons krijgen na het aanroepen van een proxy of een API, omdat de waarde niet gevonden kon worden?

Hoe gaan we daarmee om? Laten we dit eens proberen met een simpele proxy. We bekijken het bericht en als het bericht het woord ‘GREEN’ bevat, dan zullen we dat terugsturen naar de client. Als het woord ‘GREEN’ er niet in staat, dan geven we een leeg bericht terug. In de ErrorProxy3 maken we een simpele foutmelding met de tekst: ‘No Color Found’.

Error Handling WSO2 Enterprise Integrator 4
<?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>
Error Handling WSO2 Enterprise Integrator 5

Conclusie

Dit zijn een paar eenvoudige voorbeelden die laten zien hoe foutafhandeling werkt.

Het is echter beter om een generieke sequence te maken voor de foutafhandeling waarmee homogene foutberichten voor zowel de back-end fouten als de fouten die uit de fault sequence komen. Zo’n sequence kan gedefinieerd worden voor een aantal services of een specifieke servicegroep die de standaard foutvelden met specifieke waarden vult. Goed doordenken van het foutafhandelingsproces vraagt om een brede kijk op de verschillende type fouten (storingen, back-end, belangrijke foutmeldingen die de generieke fault sequence triggeren), maar ook over het soort informatie dat beschikbaar is en welke gegevens nodig zijn om fouten te kunnen verhelpen. 

Afhankelijk van het type berichten, manier van aanroepen en andere parameters kun je bepalen welke informatie nodig is en de kerngegevens uitfilteren, en daarnaast eventueel extra informatie zoals specifieke verbindingsgegevens aanbieden.

ned
Sluiten