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: 
miltonc
Product and Topic Expert
Product and Topic Expert
0 Kudos

There is a limitation in OData specifications that does not allow deep inserts 1:N for Offline applications.  However, you can use Content-ID referencing in a Change Set (batch request) to overcome this limitation.  Please refer to the OData specifications on Referencing Requests in a Change Set.  Note that the OData producer must support Content-ID referencing in order for this to work.

In our example, we will use the universally available OData Service found in http://services.odata.org.  Since this involves updating the backend data, use the link to create a full access (Read-Write) service.  The OData Service should look something similar to this.  http://services.odata.org/(S(i01sargg1imht0wuq102ghz1))/V2/OData/OData.svc/.  The OData version must be V2 and note the placement of the V2 string in the URL.

Note:  SAP Gateway 740 SP13 and above supports Content-ID referencing.  SAP Gateway 2.0 SP12 is also scheduled to support Content-ID referencing.  However, it is recommended to use the newer SAP Gateway 740 SP13 or above.

Difference between deep insert and Content-ID referencing in a change set (batch request) ?

There are quite a few similarities between deep insert and Content-ID referencing in a change set (batch request).  Both these approaches can be used to insert hierarchical data.  The table below describes some of the differences between deep insert and Content-ID referencing in a change set (batch request).

Deep Insert

Content-ID referencing in a change set (batch request)

Deep insert allows creating hierarchical data using a single payload in a single request

Multiple requests are grouped into a single request

Deep Insert is somewhat easier. The single payload in the POST request is in the same format as that of a GET request with $expand

If a MIME part representing an Insert request within a ChangeSet includes a Content-ID header, then the new entity represented by that part may be referenced by subsequent requests within the same ChangeSet by referring to the Content-ID value prefixed with a “$” character.

Most OData providers support deep insert – including Integration Gateway

Integration Gateway does not support Content-ID referencing in a batch request.  However, there are other 3rd party OData producers that support Content-ID referencing in a change set.

Limitation in OData specification does not allow for deep inserts 1:N for Offline applications

No such limitation. Hierarchical data can be inserted in both Online and Offline applications

Setting up the application definition in HCPms

Setting up the application definition in HCPms is fairly straightforward.  The publicly available OData Service does not require any authentication. To keep things simple, the application definition will also not have any authentication.  I have included a few screenshots on how to set up the application definition in HCPms.

Application ID

com.sap.batch

Name

Content ID referencing

Type

Hybrid

Description

Content ID referencing

Vendor

SAP

Security Configuration

None (not recommended)

Back-End URL

http://services.odata.org/(S(rt5puvtqg2ax2ka2tepwsonq))/V2/OData/OData.svc/

Proxy Type

Internet

Authentication

No authentication (not recommended)

Application Configuration file

[endpoint]

name=com.sap.batch

prepopulate_offline_db=Y

content_id_header_location=operation

Note:  The application configuration file is used to let HCPms know the location of the Content-ID.  This is because a lot of OData providers (including the OData Service that is being used in this blog) incorrectly requires the Content-ID as part of the operation header.  SAP Gateway correctly requires the Content-ID as part of the MIME header.  So if you are using SAP Gateway, then you would use the value ‘mime’ instead of ‘operation’.

Creating hierarchical data with 1:N relationship using Content-ID referencing in a Change Set (batch request)

The code to submit the Content-ID referencing is the same for both Online and Offline Stores.  The first step is to create the body of the request object that contains the parent and the child entities.  We will create 1 parent entity (Categories) and 2 child entities (Products).   Note that the child entities use the Content-ID (requestUri: "$1/Products") to reference the parent entity.  The navigation property is appended to the Content-ID that is being referenced.  In this case 'Products' is the navigation property.  This is appended to '$1' which is the value of the Content-ID for the parent entity. 

The request object is then created using the POST method.  The $batch is appended to the request URI (requestUri: getEndPointURL() + "/$batch") since this is a batch request.

function batchRequest() {

        var oHeaders = {

        };

var params = {

__batchRequests: [{

__changeRequests: [{

                    requestUri: getEndPointURL() + "/Categories",

method: "POST",

headers: {

"Content-ID": "1"

},

data: {

"ID": 5,

                        "Name": "Toys"

}

                },

                {

requestUri: "$1/Products",

method: "POST",

data: {

"Description": "UBS ChessMaster Software",

"DiscontinuedDate": "2013-01-01T00:00:00",

"ID": 510,

"Name": "ChessMaster 10th Edition",

"Price": "5.6",

"Rating": 5,

"ReleaseDate": "2010-01-01T00:00:00"

}

                },

                {

requestUri: "$1/Products",

method: "POST",

data: {

"Description": "Lego Blocks",

"DiscontinuedDate": "2013-01-01T00:00:00",

"ID": 511,

"Name": "Hasbro Ltd",

"Price": "23.50",

"Rating": 4,

"ReleaseDate": "2010-01-01T00:00:00"

}

                }

                ]

            }

            ]

        };

        oHeaders['Authorization'] = authStr;

        var request = {

headers: oHeaders,

requestUri: getEndPointURL() + "/$batch",

method: "POST",

            data: params

        };

OData.request(request, responseCallback, errorCallback, OData.batchHandler);

    }

Running the application (Online)

Running the application in Online mode is simple.  After you Onboard successfully, click on the Read button.  You should see 9 entries for the Products table.

Browse to the OData Service to confirm there are 9 entries for Products as well…  Also confirm there are 3 entries for Categories.

http://services.odata.org/(S(rt5puvtqg2ax2ka2tepwsonq))/V2/OData/OData.svc/Products

http://services.odata.org/(S(rt5puvtqg2ax2ka2tepwsonq))/V2/OData/OData.svc/Products/$count

http://services.odata.org/(S(rt5puvtqg2ax2ka2tepwsonq))/V2/OData/OData.svc/Categories

http://services.odata.org/(S(rt5puvtqg2ax2ka2tepwsonq))/V2/OData/OData.svc/Categories/$count

Click on the Batch request – Insert button.  This should submit both the Parent and the Child entities to the backend.  Click on Read button and notice there are 11 entries for the Product table.

Browse to the OData Service to confirm there are 11 entries for Products as well…  Also confirm there are 4 entries for Categories.

http://services.odata.org/(S(rt5puvtqg2ax2ka2tepwsonq))/V2/OData/OData.svc/Products

http://services.odata.org/(S(rt5puvtqg2ax2ka2tepwsonq))/V2/OData/OData.svc/Products/$count

http://services.odata.org/(S(rt5puvtqg2ax2ka2tepwsonq))/V2/OData/OData.svc/Categories

http://services.odata.org/(S(rt5puvtqg2ax2ka2tepwsonq))/V2/OData/OData.svc/Categories/$count

Note:  Since we are hard-coding the ID values, you cannot insert the same values again.

Running the application (Offline)

Running the application in Offline mode is simple as well.  After you Onboard successfully, you must open the Offline Store.  After the Offline Store is opened (the status will indicate that it is opened), click on Read.

Browse to the OData Service to confirm there are 9 entries for Products as well…  Also confirm there are 3 entries for Categories.

http://services.odata.org/(S(rt5puvtqg2ax2ka2tepwsonq))/V2/OData/OData.svc/Products

http://services.odata.org/(S(rt5puvtqg2ax2ka2tepwsonq))/V2/OData/OData.svc/Products/$count

http://services.odata.org/(S(rt5puvtqg2ax2ka2tepwsonq))/V2/OData/OData.svc/Categories

http://services.odata.org/(S(rt5puvtqg2ax2ka2tepwsonq))/V2/OData/OData.svc/Categories/$count

Click on the Batch request – Insert button.  This should submit both the Parent and the Child entities to the local Offline Store. Click on Read button and notice there are 11 entries for the Product table.  Note:  The relationship is established between the Parent and the Child entities because we are using Content-ID referencing when performing the insert.

Browse to the OData Service to confirm there are only 9 entries for Products.  This is because the insert was done against the local Offline Store only.  Also confirm there are 3 entries for Categories.

http://services.odata.org/(S(rt5puvtqg2ax2ka2tepwsonq))/V2/OData/OData.svc/Products

http://services.odata.org/(S(rt5puvtqg2ax2ka2tepwsonq))/V2/OData/OData.svc/Products/$count

http://services.odata.org/(S(rt5puvtqg2ax2ka2tepwsonq))/V2/OData/OData.svc/Categories

http://services.odata.org/(S(rt5puvtqg2ax2ka2tepwsonq))/V2/OData/OData.svc/Categories/$count

Click on Flush Store. After flush is complete (status will indicate that flush is complete), click on Read.  You will notice that there are still 11 entries for the Products table.  Behind the scenes, the new rows have now been sent to the backend.

Browse to the OData Service to confirm there are 11 entries for Products as well…  Also confirm there are 4 entries for Categories.

http://services.odata.org/(S(rt5puvtqg2ax2ka2tepwsonq))/V2/OData/OData.svc/Products

http://services.odata.org/(S(rt5puvtqg2ax2ka2tepwsonq))/V2/OData/OData.svc/Products/$count

http://services.odata.org/(S(rt5puvtqg2ax2ka2tepwsonq))/V2/OData/OData.svc/Categories

http://services.odata.org/(S(rt5puvtqg2ax2ka2tepwsonq))/V2/OData/OData.svc/Categories/$count

Additionally, you can also click on Refresh Store.  Note:  Since we are hard-coding the ID values, you cannot insert the same values again.

Viewing contents of the Offline Store (Optional)

Starting with SAP Mobile Platform SDK SP11, a utility called iLoData.exe is shipped along with the installation files.  This utility is useful for reading the contents of the Offline Store.  In addition, this utility can be used for performing CUD operations as well.  Flush and Refresh can also be executed using this utility.

  • Browse to the <Install Media>\modules\OfflineODataTools folder. There is a zip file named OfflineODataTools.zip.  Unzip the file to extract iLoData.exe.
  • Copy the Offline Store UDB files.  For Windows hybrid application, this can be found under %localappdata%\Packages\<Your package folder>.  There will be 2 UDB files.  Copy them both to the same location as the iLoData.exe.  For example – ProductsOfflineStore.udb, ProductsOfflineStore.rq.udb
  • Run iLoData.exe with the following command to open the Offline Store.  For a complete list of arguments that can be passed, type in ilodata.exe /?

ilodata.exe service_root=com.sap.batch store_name=ProductsOfflineStore  appcid=a6de15ce-ba6a-41dd-90a2-2603573589f0

  • Run any OData commands to read the contents of the Offline Store.  For example

get /Products

get /Products/$count

get /Categories

get /Categories/$count

get /Categories(5)/Products


I have attached the index.html file for the hybrid application.  Please refer to the blog on how to set up SAP Web IDE application to run on Windows 10.  In addition, please refer to the blog on getting started with Kapsel.

2 Comments