Integration Gateway: Understanding REST data source [8]: READ – json
This blog is about Integration Gateway in SAP Mobile Platform 3.0 (SMP).
In my previous tutorial, I’ve explained that since SP06, the SMP also supports READ operation for REST data source.
That tutorial was based on xml, so today I’d like to give an example how to do the same for JSON payload.
We’ll do the payload modification using a JSON parser.
Why is this blog necessary?
In JSON, the expected structure that we have to provide in our Custom Code, is different than in case of XML.
The current example REST service doesn’t have a READ URL, so a filter has to be specified as “Relative URL
As usual, please find the relevant source files attached to this Blog.
Prerequisite
You should have gone through my tutorial regarding READ operation for REST data source:
Preparation
You might wish to read this document in order to enhance your development experience for Groovy
REST service
In this tutorial, we’re using the following REST service
http://sansad.co/api/legislators
Documentation can be found here:
Destination
In SMP, go to the Gateway Management Cockpit and create Destination for the REST service
The “Connection Test” should be successful
If you get an error message on connection test, you might consider the following:
Note that you might need to enter proxy settings in your SMP:
https://localhost:8083/Admin/ -> Settings-> System
Note that you might need to restart the SMP server after changing the proxy settings.
OData Model
Create Project
Create project of type SAP Mobile Platform OData Implementation Project.
Define OData Model
Within the OData Modeler, create one EntityType that looks as follows:
Bind data source
Bind the REST data source to the “Read” operation of our EntitySet “Customers”.
Specify the following “Relative URL”:
/api/legislators?mp_id={mp_id}
Please note:
The URL that is used by the REST service to read a single entry is, for example:
http://sansad.co/api/legislators?mp_id=2245RS
We can see that the REST service doesn’t address a single resource by a URI.
Instead, a filter parameter is used.
For us, it doesn’t matter. Since the filter parameter uses an ID, we can assume that the result will always be not more than ONE entry.
So we can safely use this URL in terms of a READ for our OData service implementation.
Custom Code
After finishing the binding wizard, we create the “Custom Code” script for Groovy language.
What do we have to do in the script?
The payload that is returned by the REST service looks as follows:
But the Integration Gateway Framework expects the following JSON structure:
{
“PropertyName1”:“PropertyValue1”,
“PropertyName2”:“PropertyValue2”
}
The following is supported as well:
{
“d”:
{
“PropertyName1”:“PropertyValue1”,
“PropertyName2”:“PropertyValue2”
}
}
In our concrete example project, we have to manipulate the REST response such that it looks like:
After we’ve modified the response string, we return it to the Integration Gateway Framework.
Which is done by setting the modified string as body to the “message” object that is passed to us as parameter.
Intermediate step
Before we start modifying the REST response, let’s do an intermediate step with a very simplified hard-coded response string.
The code looks as follows:
def Message processResponseData(message) {
message.setBody(
“{“ +
“\”mp_id\”:\”Tazeen Fatma\”,” +
“\”first_name\”:\”Tazeen\”,” +
“\”state\”:\”Uttar Pradesh\”” +
“}”);
return message;
}
Whereas the following is also working:
def Message processResponseData(message) {
message.setBody(
“{“ +
“\”d\”:” +
“{“ +
“\”mp_id\”:\”Tazeen Fatmaaaaaaaaa\”,” +
“\”first_name\”:\”Tazeen\”,” +
“\”state\”:\”Uttar Pradesh\”” +
“}”+
“}”);
return message;
}
After generate, deploy, configure and run the service, you should see the result in the browser.
Check the Result-section below for info about how to run the service.
Note:
In this hard-coded response, we’re setting less properties than defined in our OData model. But this is OK, at runtime the remaining properties will be empty.
Remember: Our OData model can be bigger than the REST-service, but it must not be smaller (which would cause exceptions at runtime).
Implement the script
Now let’s do the generic implementation.
What we have to do:
As you can see from the screenshots above, we have to
- Remove the “results” node
- Remove the Array that is indicated by [ ]
- Remove the last 2 nodes, “count” and “page”
Other than in the previous tutorial, we’ll be using a JSON parser.
Using the parser, we only have to traverse the node-tree until we reach the entry that carries the properties.
That’s it already.
Then only transform this entry back to string.
Note:
In this concrete example, I’ve reduced the amount of properties in the OData model.
Remember: it is not allowed that the OData model has less properties than the data source, which is the REST service.
Thus, we have to solve this problem, and we do it by removing the undesired properties from the REST response, before we pass it back to the Integration Gateway Framework
This can be easily done with the parser API.
In one of my previous tutorials, I’ve described in detail how to use the JSON parser.
We need to declare a dependency to the JSON parser library, which is available in SMP: com.google.gson
Open the MANIFEST.MF file and add the dependency:
Now you can implement the following code:
def Message processResponseData(message) {
message = (Message)message;
String restResponse = (String) message.getBody();
// convert payload
String convertedPayload = convertPayload(restResponse, message);
message.setBody(convertedPayload);
return message;
}
def String convertPayload(String payload, Message message){
JsonParser parser = new JsonParser();
JsonElement topElement = parser.parse(payload);
JsonObject resultsJsonObject = topElement.getAsJsonObject(); // {“results”:[{…
JsonElement resultsJsonElement = resultsJsonObject.get(“results”);
JsonArray resultsArray = resultsJsonElement.getAsJsonArray();
// since we’re performing a READ operation, we have exactly one entry
JsonObject entryObject = (JsonObject)resultsArray.get(0);
// now need to remove some properties, because they aren’t defined in our OData model
entryObject = doRefactoringForEntry(entryObject, message);
return entryObject.toString(); // transform to string and return
}
// our OData model doesn’t contain all the properties that the REST service has.
// this is not allowed. So we remove the undesired properties from the REST payload,
// in order to match the smaller model
def JsonObject doRefactoringForEntry(JsonObject entryObject, Message message){
entryObject.remove(“age”);
entryObject.remove(“attendance_percentage”);
entryObject.remove(“debates”);
entryObject.remove(“elected”);
entryObject.remove(“in_office”);
entryObject.remove(“private_bills”);
entryObject.remove(“questions”);
return entryObject;
}
The relevant line of code is
JsonObject entryObject = (JsonObject)resultsArray.get(0);
This is the entry that matches the structure that is expected by Integration Gateway. So we can basically just call its toString() method and we get what Integration Gateway needs.
Additionally to the requirement from Integration Gateway, we also remove some of the properties, as explained above.
Please note that error handling is completely missing in our sample code.
Result
After doing generate&deploy in our Eclipse project, change to your browser and open the Gateway Management Cockpit.
Assign the destination that we’ve created in the preparation step.
Invoke our OData service.
Note that we haven’t implemented the QUERY, so we have to directly invoke a URL for READ of a single entry:
Example for a READ URL for our OData service:
https://localhost:8083/gateway/odata/SAP/<your_service_name>;v=1/Customers(‘2245RS’)
The result is
Links
The prerequisite tutorial that does the same like this blog, but for XML format:
Introduction in REST data source part 3: Understanding the return structure in xml
Preparing Eclipse for Groovy scripting:
http://scn.sap.com/docs/DOC-61719
Introduction in REST datasource part 1: Understanding the return structure in xml
Introduction in REST data source part 2: Understanding the return structure in json
Installing SMP Toolkit:
Tutorial for OData provisioning in SMP:
The official documentation
http://help.sap.com/smp306svr/#section6
Data Integration
http://help.sap.com/saphelp_smp306svr/helpdata/en/7c/20051470061014a27cf7962ebae5f8/frameset.htm