Transforming SOAP backends in Ballerina (and integrating into Travis)

Paul Fremantle
4 min readMay 7, 2018

Ballerina is a new language that is designed with integration in mind.

I was at the KubeCon conference last week and someone asked me to demonstrate calling a SOAP endpoint from Ballerina. In about 10 minutes I managed to turn the SOAP service into a RESTful interface. Since then I did a small amount of refactoring which is what we’ll look at here. While there is work going on to add a SOAP connector to Ballerina, unless you need to support WS-Security, it is just fine using the XML and HTTP support. Here’s how.

First, let’s look at a sample backend SOAP service. This is a service I built a few years ago for exactly this purpose. I loosely based it on a real SOAP API (Barclaycard SmartPay) but I simplified it a bit.

You can run the SOAP service using docker as follows:

sudo docker run -d -p 8888:8080 pizak/pay

This makes the SOAP service available on port 8888. You can find the WSDL on:

http://localhost:8888/pay/services/paymentSOAP?wsdl

The service has two methods, ping and authorise. The easiest way to find this out is to point SOAPUI at it:

SOAP UI view of the WSDL

Using SOAPUI, I created a sample message for the authorise method.

Sample XML message to call the Authorise method

This XML can be cut and paste straight into a Ballerina .bal file, and then turned into an inline XML:

Inline XML in Ballerina

The ‘?’ that SOAPUI produces can be replaced with variable substitution in Ballerina using ‘{{variable}}’ syntax:

For example:

<pay:cardnumber>{{a.cardNumber}}</pay:cardnumber>

The fact XML is a genuine first class type in Ballerina really helps. For example if the tags don’t match, the Abstract Syntax Tree (AST) validation in the IDE plugin spots that. Here I’ve deliberated messed up the tags:

XML is really a first class type in Ballerina

I said I did a bit of refactoring. Here is a slightly neater version of the XML:

The XML re-factored to define the namespaces and separate the SOAP and XML body

Now we have an XML to send to the backend, we can very easily parse an incoming JSON to create it. First I created a record type to represent the incoming message:

Record definition in Ballerina

Ballerina supports direct data type mapping from incoming JSON:

An HTTP service accepting JSON and binding to a record type.

The rest of the code is pretty straightforward, as you’ll see. Its based on calling an HTTP client and sending over the XML as a POST.

The response XML can be parsed very easily. One sneaky trick is to turn it into a JSON automatically and then navigate as if it were JSON:

json j = x.toJSON({preserveNamespaces:false}).
Envelope.Body.authoriseResponse;

Once again I created a simple type AuthoriseResponse:

Record type for the JSON response

Like XML, JSON is a native type, and this can be cast directly into a JSON object, and sent back to the calling HTTP client:

Casting record types as JSON

Here is the generated sequence diagram:

Sequence diagram for soap-to-rest.bal

The final thing I’ve done is to put the whole into a package, create a test for it using testerina, and then finally setup a .travis.yml so that travis-ci.com can build and test it every time I do a git push.
I figured out how to get Travis to build Ballerina by looking at the Ballerina By Guides that Kasun has been so instrumental in. However, I added a bit of my own fun too — I quickly realised that because the backend SOAP service is dockerised I can even start this for the test:

.travis.yml excerpt

Here you can see the successful build and test on Travis:

CI for Ballerina using Travis

I hope you enjoyed seeing how effective Ballerina is at working with JSON, XML, HTTP and even SOAP.

--

--