Thursday, May 18, 2017

Handling server side issues of integration endpoints with Ballerina

Routing invocations to a backend service or chaining a bunch of services together is a common integration requirement. In such scenarios you will have to mitigate the risk of unpredictability integrating over disparate systems brings into the mix. One common way of address this risk is to utilize HTTP status codes. Ballerina makes dealing with status codes easy with the following methods found in the ballerina.net.http package,
  • getStatusCode
  • setStatusCode  
Refer to the API documentation for mode details on the methods: http://ballerinalang.org/docs/api/0.8/ballerina.net.http.html

The example below shows how getStatusCode method can be used to make invocation time decisions on an endpoint’s availability and act accordingly. Similarly, you can utilize received status codes of HTTP endpoints as an effective way of hardening your program when it’s appropriate.


package statuscode.sample;
import ballerina.net.http;
import ballerina.lang.system;
import ballerina.lang.messages;
import ballerina.lang.jsons;
import ballerina.lang.strings;
@http:BasePath {value:"/proxy"}
service ProxyService {
http:ClientConnector backend = create http:ClientConnector("http://localhost:9090");
message request = {};
json payload = `{"status":"PLACEHOLDER"}`;
@http:GET{}
resource proxyresource (message m) {
try{
string controlHeader= messages:getHeader(m,"CONTROLLER");
if (controlHeader == "faulty backend")
{
request = http:ClientConnector.get(backend, "/faultybackend", m);
int statusCode = http:getStatusCode(request);
if (statusCode > 499){
jsons:set(payload,"$.status","something went wrong with the backend service. status code: "+strings:valueOf(statusCode));
messages:setJsonPayload(request,payload);
}
}
else
{
request = http:ClientConnector.get(backend, "/backend", m);
}
reply request;
} catch (exception e){
system:log(3,"it is but a scratch!");
}
}
}

package statuscode.sample;
import ballerina.lang.messages;
import ballerina.net.http;
import ballerina.lang.system;
@http:BasePath {value:"/backend"}
service BackendService {
message response = {};
json payload = `{"status":"all good"}`;
@http:GET{}
resource backendresource (message m) {
try{
messages:setJsonPayload(response, payload);
reply response;
} catch (exception e){
system:log(3,"it is but a scratch!");
}
}
}
To try out the example create the folder structure <BALLERINA_HOME>/statuscode/sample and then create ballerina files with the content of the two gists. Package the services into a bsz archive and run it. Invoke /proxy service with a header "CONTROLLER: faulty backend" to simulate an server side error.

curl -X GET -v http://localhost:9090/proxy -H "CONTROLLER: faulty backend"

find out more about ballerina here:  http://ballerinalang.org


Note: this example was written for ballerina 0.86 and may not work with other versions.

No comments:

Post a Comment