An Endpoint can be defined as the destination for a proxy service or an API when working with the Enterprise Integrator. It can be something as simple as this URL: http://localhost:8280/services/AcmeProxy or it can be an URL that points to another location on the Internet or somewhere within your IT landscape, it really doesn’t matter.
In the samples of WSO2, we often see a simple endpoint definition i.e. simply the URL without configuring the advanced settings that have to do with endpoints that are not available or do not respond in time.
In this Endpoint blog, I am going to look into the configuration of endpoints within WSO2 EI and how we can manage error messages.
A simple proxy
I am creating a simple proxy that will take a message and send it to an endpoint. The endpoint will be created using WireMock, a simple Java Based service mocking tool that we also use in our WSO2 trainings. If you do not yet have it, you can download it.
For the Proxy, I am using a Windows based Setup of Developer Studio and WSO2 EI 6.4.0, the regular open source version of the product. Everything will be tested on Windows but for Linux and Mac it is pretty much the same.
I’m not going to show in great detail how we unzip and configure the WSO2 Enterprise integrator and developer studio/eclipse since that would make this blog quite long.
The setup is: an enterprise integrator 6.4.0 running with the port offset of zero. Started up within the developer studio environment ready to start creating proxies.
Wiremock
We are going to create a mock backend service that we can use. In this case we will use the possibility to create a mock service using a JSON file. Create a file with the following content in for instance Notepad++. Call the file service.json and store it in the mappings directory that is created under the location where WireMock is started.
"request": {
"method": "GET",
"url": "/yenlo/api/test"
},
"response": {
"status": 200,
"body": "Service is respondingn"
}
}
This is what it looks like:
Since wiremock runs on port 8080 we should now be able to use the browser to send a request to the service that we just defined. If you don’t see any service please restart WireMock. What we defined here is actually an API because we define the method in this case it’s a “GET’ as well as the URL that will use in this case /yenlo/api/test.
So we now have a backend that we can call , so let’s do it, let’s create an API in developer studio.
I’m assuming that you are familiar with developer studio/Eclipse. It is the development environment frequently used for development of EI artifacts. If you are not familiar, I might suggest that you will join one of our trainings on the Enterprise Integrator where we will teach you how to use developer studio and of course teach you a lot of things about the enterprise integrator as well.
In SoapUI this calls the endpoint directly:
And this is the proxy we created and the response.
I’ve stopped Wire mock so there will be no response.
This is the console output when there is no response.
[2019-04-26 15:44:27,476] [EI-Core] WARN - ConnectCallback Connection refused or failed for : localhost/127.0.0.1:8080
[2019-04-26 15:44:27,482] [EI-Core] WARN - EndpointContext Endpoint : AnonymousEndpoint with address http://localhost:8080/yenlo/api/test will be marked SUSPENDED as it failed
[2019-04-26 15:44:27,483] [EI-Core] WARN - EndpointContext Suspending endpoint : AnonymousEndpoint with address http://localhost:8080/yenlo/api/test - current suspend duration is : 30000ms - Next retry after : Fri Apr 26 15:44:57 CEST 2019
[2019-04-26 15:47:26,530] [EI-Core] INFO - SourceHandler Writer null when calling informWriterError
[2019-04-26 15:47:26,531] [EI-Core] WARN - SourceHandler Connection time out after request is read: http-incoming-2 Socket Timeout : 180000 Remote Address : /127.0.0.1:62473
Now we are going to add a log to the FaultSequence
<?xml version="1.0" encoding="UTF-8"?>
<api context="/test" name="EPTest" xmlns="http://ws.apache.org/ns/synapse">
<resource methods="GET"> <inSequence>
<send>
<endpoint>
<http method="get" uri-template="http://localhost:8080/yenlo/api/test"/>
</endpoint>
</send>
</inSequence>
<outSequence>
<send/>
</outSequence>
<faultSequence>
<log description="" level="custom">
<property expression="get-property('ERROR_CODE')" name="Error"/>
</log>
</faultSequence>
</resource>
</api>
We will redeploy this API to the server and again invoke the API with WireMock not running.
[2019-05-08 12:40:12,130] [EI-Core] INFO - LogMediator Error = 101503
The faultSequence simply gives back the error code that corresponds with the ‘Connection Failed’ situation. We can add:
<property expression="get-property('ERROR_MESSAGE')" name="MSG"/>
We now get the following error:
[2019-05-08 12:56:33,991] [EI-Core] INFO - LogMediator Error = 101503, MSG = Error connecting to the back end
This is a situation that is a bit better but what you would really give back is a correct 404 code and perhaps a message as a response (like ‘Resource can not be found’). We will actually set the response code in the faultSequence.
What we will actually do is rewrite the faultSequence a bit. We will have a Log Mediator create output for the console, and a formal message that is given to the client that calls the proxy. In Design View it looks like this:
In the source view, we see more about the actual configuration. We are only showing the faultSequence.
<faultSequence>
<log description="" level="custom">
<property expression="get-property('ERROR_CODE')" name="Error"/>
<property expression="get-property('ERROR_MESSAGE')" name="MessageSG"/>
<property expression="get-property('ERROR_DETAIL')" name="Detail"/>
<property expression=="get-property('ERROR_EXCEPTION’)" name="Exception"/>
</log>
<property name="HTTP_SC" scope="axis2" type="STRING" value="404"/>
<payloadFactory media-type="json">
<format>{ 'Error':'Connection cannot be made',
'Error Code' : $1,
'Error Message' : $2,
'Error Detail' : $3}</format>
<args>
<arg evaluator="xml" expression="get-property('ERROR_CODE')"/>
<arg evaluator="xml" expression="get-property('ERROR_EXCEPTION')"/>
<arg evaluator="xml" expression="get-property('ERROR_MESSAGE')"/>
</args>
</payloadFactory>
<respond/>
</faultSequence>
The output is:
[2019-05-08 15:02:17,424] [EI-Core] INFO - LogMediator Error = 101503, MSG = Error connecting to the back end, Trace = Error connecting to the back end, exception = null
And on the client side:
HTTP/1.1 404 Not Found
Host: localhost:8280
Accept-Encoding: gzip,deflate
Content-Type: application/json; charset=UTF-8
Date: Wed, 08 May 2019 13:02:17 GMT
Transfer-Encoding: chunked
Connection: Keep-Alive
{ 'Error':'Connection cannot be made',
'Error Code' : 101503,
'Error Message' : ,
'Error Detail' : Error connecting to the back end}
We now have an API that will respond with a 404 and a custom message response. In the next blog of the Endpoint series we will look into the way to set up error handling for multiple error codes.
Do you want to learn more about WSO2 Enterprise Integrator? Join our WSO2 Enterprise Integrator Training.