Under-fetching is a common symptom when services are created where the consumer needs to make multiple calls to obtain the results they desire. Service chaining in APIC can be created to handle such situations. You can build an API Proxy that acts as an aggregator of more than one backend services. You can implement the aggregator API Proxy by chaining calls to the backend services and combining the response data from each of these services into a single response to the consumer. Another solution for under-fetching is using GraphQL. You will learn about GraphQL in Chapter 9, Building a GraphQL API.
To build the aggregator response, you will use a combination of Invoke Policies and a GatewayScript Policy. For this use case, we will use the same backend service we have been using: https://stu3.test.pyrohealth.net/fhir/Patient/.
Previously, you have learned how to modify the titles of invoke policies, set path parameters for patient-id, and pass values to the Test capability of APIC. You will be doing that again with some slight modifications and the assistance of GatewayScript code. You can download patient-response.js from the GitHub site.
The approach you will be taking is constructing a new API definition and implementing two Invoke policies that return a different patient payload, followed by a GatewayScript that merges the responses of the two Invokes. The new skill you will learn is how to capture the response objects individually from each Invoke as query parameters. Once captured, you will filter specific fields from these responses and send a custom aggregated response back to the API consumer.
The patient-id values you will use are as follows:
- 9df54eeb-a9ac-47ec-a8f6-eb51dd7eb957
- 97e47441-b8b9-4705-bda7-248ae6ae2321
Here are the steps you should follow:
- Create a new REST API Proxy (from a target service) using the URL https://stu3.test.pyrohealth.net/fhir/Patient/. Name this proxy aggregation-service. Keep the default Base path value. Remove all the security definitions.
- In Design | Paths, create a path (/Patient) that takes two query parameters, patient-id1 and patient-id2. It should support a GET operation. Refer to Figure 4.40:
Figure 4.40 – Setting query parameters
3. In the Gateway tab | Policies, update the existing Invoke and set Title to get patient 1 and the URL to $(target-url)/$(request.parameters.patient-id1). Scroll to the bottom of the invoke policy’s properties and enter patient1-response in the Response object variable property. Refer to Figure 4.41:
Figure 4.41 – Setting the response object name
4. Drag and drop a new Invoke to the right of get patient 1. Perform step 4 again but instead use the title of get patient 2, set the URL to $(target-url)/$(request.parameters.patient-id2), and set up the response object to patient2-response. Next, you will add the aggregation code to filter data.
5. Drag and drop a GatewayScript policy to the right of get patient 2. Set the title to aggregate results. Download the GatewayScript’s code (patientResponse.js) from this chapter’s GitHub repository. Copy and paste the downloaded code into the GatewayScript as shown in Figure 4.42. Click Save to save your API.
Figure 4.42 – Aggregation GatewayScript
A quick review of the JSON code would be helpful. The code uses the context.get(‘response object name’) method to retrieve the response objects you designated. It utilizes the technique of converting the response returned by the backend service to a JSON object using the JSON.parse() method. The converted JSON object can then be navigated using the dot notation method. For example, to access the family name of patient 1, you can use patient1Response.name[0].family. The aggregated response is stored in the patientResponse variable. This aggregated response is finally sent as the output to the API caller using the context.message.body.write method:
var patient1Response =
JSON.parse(context.get(‘patient1-response.body’));
var patient2Response =
JSON.parse(context.get(‘patient2-response.body’));
var patientResponse= {
patients: [{
“lastName” :
patient1Response.name[0].family,
“firstName”:
patient1Response.name[0].given[0]
},
{
“lastName” :
patient2Response.name[0].family,
“firstName”:
patient2Response.name[0].given[0]
}]
}
context.message.header.set(‘Content-
Type’,”application/json”);
context.message.body.write(patientResponse);
You are now ready to test. Again, you will use the Test tab to execute the API.
6. Click on the Test tab and provide the query parameters:
Patient1 = 9df54eeb-a9ac-47ec-a8f6-eb51dd7eb957
Patient2 = 97e47441-b8b9-4705-bda7-248ae6ae2321
Click Send to test your API. Your results should appear as shown in Figure 4.43:
Figure 4.43 – A successful test of aggregation of response
Your results should be as follows:
{“patients”:[{“lastName”:”Parks”,”firstName”:”Christop
her”},{“lastName”:”van de Heuvel”,”firstName”:”Pieter”
}]}
Well done!
The previous example covered some important aspects of API development. You were introduced to the concept of service chaining and techniques to access an Invoke Policy’s response objects in a GatewayScript policy to create an aggregated response. Capturing the backend service response in a Response object variable is just one of many advanced features provided by the Invoke Policy.
One of the most important aspects of any software development is to build software that handles exception conditions that arise during that software’s execution. APIC’s development framework also provides you with a catch IBM extension and a throw policy to handle exceptional scenarios. The following example will demonstrate the technique of managing such error conditions within an API Proxy.