Introduction: OData $batch Processing with Content ID in SAP Gateway
Thanks for your attention. If you are the one of frequent SCN readers, you would think I’m publishing yet another H2G blog 🙂 – yes this is important topic hence I wrote it.
Do you know OData? – Most likely yes.
Have you ever used OData? Most likely yes too.
And – do you know about “Content ID”? – Perhaps no.
“Content ID” is nothing new, it has been defined in the standard OData specification for a while, based on the idea that any OData app can take advantage of when building relationships between entities. A section of “Batch Processing” (2.2.1. Referencing Requests in a Change Set) describes what it is and how to use it – but without any context, you would have no idea when we use it.
Why we need this?
One very common use case is – OData providers need to support Content ID when we use Header-Items (or “Parent-Children”) data with Offline Store of SMP3/HCPms OData SDK.
Let’s have a quick look at how it works in an offline store. If you’re familiar with Offline Store, it is nothing new. As an OData $batch request, we create a set of header & item entities in the offline store locally. Each entity has its own create request via OData client API.
Here comes the interesting part. To add related child entities to a parent entity, you need to know, or be able to reference, the parent entity’s ID. The “Content ID” acts as a reference to the parent entity’s ID. As you see, a Content ID has a prefixed value with a “$” character.
For example, by using the Content ID referencing, you can refer the items with the resource navigation path “$100/ToItems”. $100 indicates the header entity by using Content ID. As it is still created locally, those entities don’t have any finalized key that will be given by the OData services.
Time to flush the local entities. These entities needs to be flushed via OData $batch request.
Once your $batch flush goes successfully, the OData services handle “Content ID” and assign key(s) to the entities for all the set of headers & items on the backend side. Most likely you want to do refresh too.
Got it? As you see, Content ID plays a critical role to handle header-item relationship with Offline Store during OData $batch processing. In other words – to create child items for entities within a change set of $batch request.
To give you some more practical idea from the OData client SDK perspective, here’s a small piece of code that demonstrates the idea in iOS API (Android, Windows, and Kapsel API follow the same rule):
01 SODataRequestParamBatchDefault *batch = [[SODataRequestParamBatchDefault alloc] init]; 02 SODataRequestChangesetDefault *changeset = [[SODataRequestChangesetDefault alloc] init]; 03 04 SODataRequestParamSingleDefault *parentReq = [[SODataRequestParamSingleDefault alloc] initWithMode:SODataRequestModeCreate resourcePath:@"/HeaderSet"]; 05 parentReq.payload = parentEntity; 06 parentReq.contentID = @"100"; 07 08 SODataRequestParamSingleDefault *childReq = [[SODataRequestParamSingleDefault alloc] initWithMode:SODataRequestModeCreate resourcePath:@"$100/ToItems"]; 09 childReq.payload = childEntity; 10 11 [changeset.requestParams addObject:parentReq]; 12 [changeset.requestParams addObject:childReq]; 13 14 [batch.batchItems addObject:changeset]; 15 16 [store scheduleRequest:batch delegate:self];
#01 & #02: creating a batch and changeset object.
#04 – #06: is for creating parent entity – as #04 indicates, it is a Header entity. You see the #06 that is assigning Content ID.
#08 – #09: for child entity. #08 indicates the child entityset is described as “$100/ToItems” that is navigation resource path from parent to children.
#11 – #16: execute a $batch request.
That’s all the Content ID referencing from client perspective. Now you get the idea of what Content ID is – and the next question is how to implement OData services that support it.
The aim of the following H2G is how to implement OData $batch processing with Content ID in SAP Gateway.
Note: This introductory page focuses on the Offline Store in SMP3/HCPms OData SDK. However, Content ID Referencing could make sense (or useful) when we have these reasons in general:
- You want (or need) to create parent and one or more related child entities in the same transaction.
- You choose to use a OData $batch changeset.
- You choose to create the relationship by issuing a POST request to the navigation URL of the parent entity (rather than, for example, using a deep insert)
- You do not have enough information to construct the edit URL of the parent entity (because some part of the key is generated)
Perhaps another common use case in which we want to use Content ID is when we create a header-items data via HANA Cloud Integration. HCI supports $batch request as a runtime. My buddy colleague Midhun VP wrote a tip of how to execute the $batch call through HCI.
Content ID Referencing is supported in the following versions:
- SAP Gateway 2.0 SP12+
- SAP NetWeaver 740 SP13+
- SAP NetWeaver 750
You have a skillset of building basic CRUD OData services with SAP Gateway Workbench (tx code: SEGW) as explained here: #1 – OData CRUD Crash Course – Getting ready with offline store
Are you ready? Let’s hop in the implementation.
Great blog Ken!
Very well explained
The best reference to explain Content ID for everyone! Well done!
There is a feature request for OpenUI5 on GitHub to support Content-ID: Enh. Req.: Please support content id referencing in sap.ui.model.odata.v2.ODataModel.create/createEntry, etc. · Issue #9…
We tried implementing batch with content-ID against the offline store. When creating headers, it works fine, but while referencing items ie. ($1/toOrderItems) it gives an error saying unhandled payload type (for ios) or invalid resource path (for android) . Same payload works perfectly fine for online requests. What must be the reason?
Were you able to run it successfully with REST client, and the problem only happens via the SDK?
Sorry for the late response!
Our Kapsel SDK was outdated, we updated the plugins to 3.15 and it worked perfectly! Thanks!!
Hi Kenichi Unnai
Thanks for this great blog, I have a doubt in terms of UI5 implementation. I tried as below in UI5, I get an error. on the $1/HeadItemNav section
Meanwhile if I just use like below, it got through, but I have a difficulty in getting pushing in value for CONTENT_ID_REF.
Your advice is much appreciated.
Have you worked this out? I think it is not possible to add content id Ref as a header field, as content-ID is already in the header, but also sapui5 odata model is not able to createEnry(("/$1....)?