WSO2TORIAL: Error Handling in WSO2 ESB with WireMock

Posted by Dusan Dević on 26 May, 2016
Dusan Dević

Endpoint error handling is a key part of any successful ESB deployment.

Messages can fail or be lost due to various reasons in a real TCP network. When an error occurs, if the ESB is not configured to accept the error, it will mark the endpoint as failed, which leads to a message failure. By default, the endpoint is marked as failed for quite a long time, and due to this error, subsequent messages can get lost.

To avoid lost messages, you should configure WSO2 ESB error handling at the endpoint level. 

ESB often has to deal with many wire level protocols, messaging standards, and remote APIs. Applications and networks can be full of errors. Network routers and links get into states where they cannot pass messages through with the expected efficiency. These error conditions are very likely to cause a fault or trigger a runtime exception in the ESB.

Let's see how we can simulate an error in order to understand how ESB behaves in such situations.     

Install WireMock:

We'll need a dummy backend service which will respond to our messages. For such purpose we can make use of WireMock, a piece of software which will act as our API. Actually, with WireMock we'll define a few endpoints with different behaviors and set our WSO2 ESB to handle those.    

  • Download WireMock from here;
  • Open your Terminal;
  • Go to your Home Directory: cd ~
  • Create directory wiremock: mkdir wiremock
  • Move downloaded jar to wiremock directory you just created:
    mv Downloads/wiremock-1.57-standalone.jar wiremock/
  • Go to wiremock directory: cd wiremock
  • Run WireMock as a Standalone Process: java -jar wiremock-1.57-standalone.jar

If you have Java JDK and the port 8080 is not already taken, you should see similar output as following:

Wiremock.png

During the first start, WireMock will create two directories: mappings and __files. You can see them alongside .jar file in your ~/wiremock directory.

In mappings directory create a file delay.json with the following content:

{
    "request": {
        "method": "GET",

        "url": "/api/delay30"
    },
    "response": {
        "status": 200,
        "body": "30 seconds passed so here I am!",
        "fixedDelayMilliseconds": 30000
    }
}

In order to apply this, you need to restart WireMock Server. Go to the terminal window where you started it, press CTRL + C and then start it again.

Basically what we did here is creation of a new dummy webservice available at http://localhost:8080/api/delay30, which will respond with HTTP Status 200 and a proper body message, but after a delay of 30 seconds. Note that delay.json file name is not important, you can rename it if you like and you'll have a few independent json files in this folder, one per each dummy web service. After every change you'll need to restart WireMock Server.

STEP 1: Create endpoint

  • First we need to create the endpoint. On ESB Console click on Main tab, then Manage > Service Bus > Endpoints > Add Endpoint;
  • Choose Address Endpoint;
  • On the next screen fill the form as follows:
    • Name: delay30
    • Address: http://localhost:8080/api/delay30
    • Endpoint Timeout State
      • Retries Before Suspension: 3
      • Retry Delay(Millis): 500
    • Connection Timeout
      • Action: Execute fault sequence
      • Duration (Millis): 10000
    • Save and Close.

If you prefer to work with XML directly, here is the code that will be generated:

<endpoint xmlns="http://ws.apache.org/ns/synapse" name="timeout30">
   <address uri="http://localhost:8080/api/delay30">

      <suspendOnFailure>
         <progressionFactor>1.0</progressionFactor>
      </suspendOnFailure>
      <markForSuspension>
         <retriesBeforeSuspension>3</retriesBeforeSuspension>
         <retryDelay>500</retryDelay>
      </markForSuspension>
      <timeout>
         <duration>10000</duration>
         <responseAction>fault</responseAction>
      </timeout>
   </address>
</endpoint>

Here we defined a new endpoint called timeout30. Invoke to that endpoint will fire a HTTP request to http://localhost:8080/api/delay30, which is actually our dummy web service we created with WireMock. We told ESB that it should fire up to 4 requests to that endpoint (one initial and 3 retries). When an error occurs and the endpoint is set to the Timeout state, the ESB can try to send up to three more messages. If the next 3 messages sent to this endpoint result with an error (for example: there is no response after 10 seconds), ESB will mark this endpoint as SUSPENDED.


STEP 2: Define a Proxy

Now we should create a proxy which will call our endpoint. 

  • On ESB Console click Main tab and under Services section choose Add > Proxy Service > Custom Proxy;
  • In the 1st step Proxy Service Name should be lab01, click next;
  • In the 2nd step under section Define Endpoint, choose Use Existing Endpoint and select timeout30 from the list;
  • In the last step choose Define Inline option for the both sections.
    • For Out Sequence click on Create and choose Add > Core > Log. Click on the new Log button and in Log Mediator settings set Log Category to INFO and Log Level to Simple;
    • Add the Send mediator to Out Sequence;
    • Click on Update and finally Save & Close;
    • Do similar for Fault Sequence, but only choose ERROR for Log Category.

Make sure your Proxy looks like this:

<?xml version="1.0" encoding="UTF-8"?>
<proxy xmlns="http://ws.apache.org/ns/synapse"

       name="lab01"
       transports="http,https"
       statistics="disable"
       trace="disable"
       startOnLoad="true">
   <target endpoint="timeout30">
      <outSequence>
         <log/>
         <send/>
      </outSequence>
      <faultSequence>
         <log category="ERROR"/>
      </faultSequence>
   </target>
   <description/>
</proxy>

STEP 3: Test Everything

Until now we have an endpoint together with the proxy service. 

As we set desired timeout to 10 seconds, after that period ESB should fire a fault from the endpoint and the fault sequence from our proxy will be executed. As our fault sequence is really simple, you should see something like this in ESB Terminal Output:

[2016-02-23 05:46:39,600] ERROR - LogMediator To: /services/lab01.lab01HttpEndpoint, MessageID: urn:uuid:5481796e-5fa3-46de-954d-252e78ddd16c, Direction: request

Now point your browser to:

http://localhost:8280/services/lab01.lab01HttpEndpoint and watch ESB Terminal Output (that's the tab in your OS Terminal where you started ESB).

Also, if you check Endpoints section in ESB Console Panel (Manage > Service Bus > Endpoints), you should see that timeout30 endpoint is actually switched off (suspended). ESB did this automatically when desired conditions were satisfied:

WSO2_ESB_Manage_Endpoints.png 

Now switch it on with click Switch On link under Action column. 

We'll now increase timeout time on ESB. Edit our timeout30 endpoint and set Duration (Millis) to any value larger than 30000:

  • Connection Timeout
    • Action: Execute fault sequence
    • Duration (Millis): 35000

Save the changes and then test again from the web browser: http://localhost:8280/services/lab01.lab01HttpEndpoint

Output message should be similar to this:

[2016-02-23 06:18:35,489]  INFO - LogMediator To: http://www.w3.org/2005/08/addressing/anonymous, WSAction: , SOAPAction: , MessageID: urn:uuid:992c724b-07ca-49fd-83bc-e930d717702f, Direction: response

Also note that in this case our endpoint is still in ACTIVE state.

In this simple example you learned how WSO2 ESB will behave in exceptional situations. This tutorial is a part of Yenlo's WSO2 Training Material. Feel free to contact us if you are interested for WSO2 Support.

Thanks to Domenique Mulder for his contribution to this  blog.

WSO2TORIALS help you to change, update or improve WSO2 products and are based on our experiences with the products. WSO2TORIALS will guide you step by step with minimal knowledge required.   WSO2TORIAL.jpeg    
   

 

 

  Check our webinars

 

 

Topics: WSO2 ESB

Dusan Dević

Written by Dusan Dević

Dusan is a passionate full-stack developer with more then 6 years of experience, especially with web development. He is very interested in IoT and modern technology in general. From 2015 he works as Integration Consultant at Yenlo, mostly with WSO2-IS, WSO2-DAS, Java and AngularJS.