Technology Blogs by SAP
Learn how to extend and personalize SAP applications. Follow the SAP technology blog for insights into SAP BTP, ABAP, SAP Analytics Cloud, SAP HANA, and more.
cancel
Showing results for 
Search instead for 
Did you mean: 
CarlosRoggan
Product and Topic Expert
Product and Topic Expert
0 Kudos

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:

http://sansad.co/

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:

http://scn.sap.com/community/developer-center/mobility-platform/blog/2015/03/06/integration-gateway-...

Introduction in REST data source part 3: Understanding the return structure in xml

http://scn.sap.com/community/developer-center/mobility-platform/blog/2015/02/12/integration-gateway-...

Preparing Eclipse for Groovy scripting:

http://scn.sap.com/docs/DOC-61719

Introduction in REST datasource part 1: Understanding the return structure in xml

http://scn.sap.com/community/developer-center/mobility-platform/blog/2015/02/10/understanding-rest-d...

Introduction in REST data source part 2: Understanding the return structure in json

http://scn.sap.com/community/developer-center/mobility-platform/blog/2015/02/11/integration-gateway-...

Installing SMP Toolkit:

http://scn.sap.com/community/developer-center/mobility-platform/blog/2014/08/22/how-to-install-sap-m...

Tutorial for OData provisioning in SMP:

http://scn.sap.com/community/developer-center/mobility-platform/blog/2014/06/10/creating-an-odata-se...

The official documentation

http://help.sap.com/smp306svr/#section6

Data Integration

http://help.sap.com/saphelp_smp306svr/helpdata/en/7c/20051470061014a27cf7962ebae5f8/frameset.htm