Service Mashup

Service Mashup is an aggregator of Service Callouts configured as asynchronous. By allowing external callouts to execute in parallel, Service Mashup provides an advantage over execution time of the call to the centralizing API by making better use of time, as demonstrated below.

Configuring the interceptor

The image below shows the settings for the interceptor:

mediation service mashup
  • Service callouts to wait: it lists all available asynchronous Service Callout instances that are not Fire and Forget and that are not contained in another Service Mashup.

  • Timeout(ms): it determines the timeout in milliseconds. If no value is inserted, the longest timeout configured among the selected Service Callouts will be applied.

  • Abort if any request fails: if selected, the request will be aborted if any of the Service Callouts fails. A failure occurs when the status code of the response is different from the expected.

How it works

To show how Service Mashup works, let’s consider the following case:

An organisation, the LSA (Lost Souls' Alliance), will develop a central API, LSA Communication, which will be able to send, via POST, the same message (or command) to people inside and outside the organisation. This API will be registered under the domain lsa.org.mx.

The message, sent as a JSON in the body of the call, will be:

{
  "message": "Join or Die! Viva la revolución!",
  "author": "Salvador Limones"
}

The case of internal communication has been addressed in how Internal API Call works. The case of the external one, in how Service Callout works. Now let’s combine these two communications into a single call.

The following images show, respectively, the sequence of the interceptors in the API flow and the settings used in the Service Mashup interceptor, which waits for the responses of the two Service Callout interceptors to continue the flow:

mediation service mashup flow
mediation service mashup config

The settings used for the Internal API Call interceptor are the same as described in how it works. Those used for the two Service Callout interceptors are also the same as those described in how they work, except that the Asynchronous field has been checked and therefore the use of Service Mashup becomes necessary.

Unlike the case where the two Service Callout interceptors were configured to act synchronously, now both are executed in parallel. To take advantage of the waiting time, the Internal API Call is called after them, being executed while the other two calls are in progress.

At the end of the execution of the Internal API Call, the returned response, which is an object of type ApiResponse, is stored in the context variables. Next, the Service Mashup waits for the responses returned by the two Service Callout interceptors, which are objects of type RESTResponse, and also stores these responses in the context variables. To retrieve all responses, you must create a custom interceptor that accesses $call.contextVariables.get(“Variable Name”).

Below is the code for the custom JavaScript interceptor that will be used to capture all the responses and include the bodies and status in the final response:

// Capture the response from Internal API Call
var respRadio = $call.contextVariables.get('radioMessages');

// Capture the responses from Service Callouts
var respManny = $call.contextVariables.get('mannyMessage');
var respMeche = $call.contextVariables.get('mecheMessage');

// Create an ApiResponse Object for this call
$call.response = new com.sensedia.interceptor.externaljar.dto.ApiResponse();
$call.response.addHeader('Content-Type', 'application/json');

// JSON template for returned messages
var respBody = JSON.parse(`
    {"radio": {"status": 0, "body": {}},
     "pigeonManny": {"status": 0, "body": {}},
     "pigeonMeche": {"status": 0, "body": {}}}
`);

// The status returned is an Object, not a Number
var statusRadio = respRadio.getStatus();
var statusManny = respManny.getStatus();
var statusMeche = respMeche.getStatus();

// The intValue method is called to get a Number object
respBody.radio.status = statusRadio.intValue();
respBody.pigeonManny.status = statusManny.intValue();
respBody.pigeonMeche.status = statusMeche.intValue();

// A body is inserted only if a 200 status is returned
// Get the body from an ApiResponse
if (statusRadio == 200){
    respBody.radio.body = JSON.parse(respRadio.getBody().getString("UTF-8"));
}

// Get the body from a RESTResponse
if (statusManny == 200){
    respBody.pigeonManny.body = JSON.parse(respManny.getResponseText());
}

if (statusMeche == 200){
    respBody.pigeonMeche.body = JSON.parse(respMeche.getResponseText());
}

// Set the modified body into the ApiResponse
$call.response.getBody().setString(JSON.stringify(respBody), "UTF-8");

// Set return status as 200
$call.response.setStatus(200);

Finally, the body of the response of the POST call to the all-messages resource of LSA Communication will be:

{
  "radio": {
    "status": 200,
    "body": {
      "messages": [
        {
          "message": "I've already joined, Sal, a year ago. Is this just a test message?",
          "author": "Eva"
        }
      ]
    }
  },
  "pigeonManny": {
    "status": 200,
    "body": {
      "message": "I'm already dead...",
      "author": "Manuel Calavera"
    }
  },
  "pigeonMeche": {
    "status": 200,
    "body": {
      "message": "Only if it has cars, as I was given one purpose, one skill, one desire: to DRIVE!",
      "author": "Glottis"
    }
  }
}
Thanks for your feedback!
EDIT

Share your suggestions with us!
Click here and then [+ Submit idea]