Tuesday, April 8, 2014

Using Script mediators to build a Json payoad with optional parameters in a connector for WSO2 ESB

When making requests to an API, it's very important to identify the parameters that are required (mandatory) and that are optional. It's also essential to know the type of those parameters and the proper way of sending them to the API such as if the api supports REST and we are making a REST/json request, we must ensure that the request that we are sending is a valid json string.

In this post, I wanted to focus bit more on how to handle body parameters that are optional. The concept beind using optional parameters are, it says, a user need not mandatory send those values to call that function but if they wish to set those values as well, then the function should support them. 

As in my other similar posts, let me take a real word example to demonstrate this.

API:                     Google Calendar
Function:             CalendarList: insert
Reference Link: https://developers.google.com/google-apps/calendar/v3/reference/calendarList/insert

The above mentioned request is an HTTP POST request to create a new Calendar List Entry.According to the API documentation, it expects a list of values to be sent through the request body and the request body consists of both required and optional parameters. 

So, these should be handled carefully within the synapse template of the connector. The concept is clear. We are going to set a payload factory to send the request body parameters and the required parameters can be directly hard coded. Also, the optional parameters will be added to the request body checking the condition that the parameter holds a value (it should be not null and not empty to be added to the payload).

The below shown code from the synapse template will clearly explain you how this task is handled.

Note that this function has id as the only request body parameter that is considered to be required and all the rest of the parameters are optional.

The request body parameters should be declared as below;

<!-- Required parameters -->
<parameter name="id" description="Identifier of the calendar." />

<!-- Optional parameters -->
<parameter name="defaultReminders" description="A list of authenticated users for this calendar. Each item has method and minutes." />
<parameter name="foregroundColor" description="The foreground color of the calendar in the format '#ffffff'." />
<parameter name="isHidden" description="Whether the calendar has been hidden from the list." />
<parameter name="notificationSettings" description="The method used to deliver the notification. " />
<parameter name="summaryOverride" description="The summary that the authenticated user has set for this calendar." />

Property mediators should be set to the above parameters to map with the proxy as below within the <sequence>.

<property name="uri.var.defaultReminders" expression="$func:defaultReminders" /> 
<property name="uri.var.foregroundColor" expression="$func:foregroundColor" /> 
<property name="uri.var.isHidden" expression="$func:isHidden" /> 
<property name="uri.var.notificationSettings" expression="$func:notificationSettings" /> 
<property name="uri.var.summaryOverride" expression="$func:summaryOverride" />

Then the payload factory can be added with the required (mandatory) parameters as shown below.

<!-- Building request with mandatory params -->
<payloadFactory media-type="json">
<format>
{
"id":"$1"
}
</format>
<args>
<arg expression="get-property('uri.var.id')" />
</args>
</payloadFactory>

Finally, the script mediator can be used to add the optional request body parameters on checking the conditions as below.

<script language="js">
<![CDATA[        
//request body param variables
var defaultReminders = mc.getProperty('uri.var.defaultReminders');
var foregroundColor = mc.getProperty('uri.var.foregroundColor');
var isHidden = mc.getProperty('uri.var.isHidden');
var notificationSettings = mc.getProperty('uri.var.notificationSettings');
var summaryOverride = mc.getProperty('uri.var.summaryOverride');                                    
//getting the json payload of the message context.
var payload = mc.getPayloadJSON();
//if values set for defaultReminders Array, then add it to the payload
if ( defaultReminders != null && defaultReminders != "") { 
payload.defaultReminders = eval("("+defaultReminders+")");
}
//if a value is set for foregroundColor , then add it to the payload
if (foregroundColor != null && foregroundColor != "") {
payload.foregroundColor = foregroundColor;
}
//if isHidden parameter is set, add it to the payload
if (isHidden != null && isHidden != "") {
payload.hidden = isHidden;
}
//if values set for notificationSettings Object, then add it to the payload
if ( notificationSettings != null && notificationSettings != "") { 
payload.notificationSettings = eval("("+notificationSettings+")");
}
//if values set for summaryOverride , then add it to the payload
if (summaryOverride != null && summaryOverride != "") {
payload.summaryOverride = summaryOverride;
}
//add the payload to the message context
mc.setPayloadJSON(payload);
]]>
</script>

Finally you can use the call mediator by setting required or optional URL parameters to call the function appropriately.

Hope it was useful to you.