SAP / cloud-sdk-js

Use the SAP Cloud SDK for JavaScript / TypeScript to reduce development effort when building applications on SAP Business Technology Platform that communicate with SAP solutions and services such as SAP S/4HANA Cloud, SAP SuccessFactors, and many others.
Apache License 2.0
162 stars 56 forks source link

Ability to reference between requests in oData ChangeSets #2708

Open carlonnheim opened 2 years ago

carlonnheim commented 2 years ago

Is your feature request related to a problem? Please describe. We need to cross-reference between requests within a changeset of a oData batch request. This is important in any scenario where we need to create an entity and then call an action on it within the same batch request to achieve an atomic operation.

Example: Posting Time Entries to SAP Business ByDesign. The process requires two steps - first create the time entry and then call the release action on the new entry.

Describe the solution you'd like We need the ability to set and get the Content-ID header of the individual requests. An auto-generated Content-ID was recently introduced in https://github.com/SAP/cloud-sdk-js/issues/2255, but to my understanding there is no mechanism to retrieve it and reference it in subsequent requests.

Describe alternatives you've considered We are currently processing the steps in separate requests. This has two drawbacks. Turnaround time is slower, which has notable impact on scenarios where a user is interactively processing the transaction in the external application. The other drawback is consistency - since we cannot make the operation atomic we get additional issues to handle in the external application (identify and recover from the inbetween state - time entry is posted but not released).

Impact / Priority

Affected development phase: Development

Impact: Impaired

Timeline: Go-Live in 3 months.

Additional context For SAP Business ByDesign in particular, actions are in general not "bound", but follow a pattern of service/SomeAction?ObjectID='nnn' rather than service/SomeEntityCollection('nnn')/SomeAction. This might further complicate the realization of this scenario with ByD in particular (even with the Content-ID present we cannot do $thecontentid/SomeAction). Maybe @knutheusermann has some input on the ByD specific aspect?

The feature itself is generic to any oData v2 or v4 scenario however, not only the ByD sample scenario.

marikaner commented 2 years ago

Hey @carlonnheim,

you could configure your request to use a custom header (.addCustomHeaders), where you set your own Content-ID. Would this work for you or do you need to access generated IDs instead?

On a different note, I fail to recognize how your comment about unbound actions relates to this issue. Do you need to send unbound actions with batch? FYI: The SAP Cloud SDK currently only supports unbound actions and functions.

carlonnheim commented 2 years ago

Hi @marikaner , thanks for the quick response.

The main aspect is to reference back to the created entity. You can refer to the sample batch request in the oData v2 documentation, section 2.2.1.

POST /service/$batch HTTP/1.1 
Host: host 
Content-Type: multipart/mixed; boundary=batch_36522ad7-fc75-4b56-8c71-56071383e77b 

--batch_36522ad7-fc75-4b56-8c71-56071383e77b 
Content-Type: multipart/mixed; boundary=changeset_77162fcd-b8da-41ac-a9f8-9357efbbd621 
Content-Length: ###       

--changeset_77162fcd-b8da-41ac-a9f8-9357efbbd621 
Content-Type: application/http 
Content-Transfer-Encoding: binary 
Content-ID: 1

POST /service/Customers HTTP/1.1 
Host: host  
Content-Type: application/atom+xml;type=entry 
Content-Length: ###

<AtomPub representation of a new Customer> 

--changeset_77162fcd-b8da-41ac-a9f8-9357efbbd621 
Content-Type: application/http 
Content-Transfer-Encoding: binary 

POST $1/Orders HTTP/1.1 
Host: host 
Content-Type: application/atom+xml;type=entry 
Content-Length: ### 

<AtomPub representation of a new Order> 

--changeset_77162fcd-b8da-41ac-a9f8-9357efbbd621-- 
--batch_36522ad7-fc75-4b56-8c71-56071383e77b--

In this sample, there is first a POST request to create an entity. This has Content-ID: 1. Then there is a subsequent POST request to create children, referencing the created entity as POST $1/Orders. The reference itself is opaque, the actual value does not matter. Ability to set it can make application coding easier, but generated ID's should in general work just as well. In our scenario the second request would be a bound action (POST $1/SomeAction), but in essence the same pattern.

This is also why the bound/unbound makes a difference. The Content-ID reference identifies the URI if the created resource, i.e. referencing a bound action underneath that resource makes sense, whereas referencing one of its properties to call an unbound action, with that property as parameter does not.

Thanks! //Carl

marikaner commented 2 years ago

Hey Carl,

ok got it, thank you. Then my understanding is that these are actually 3 feature requests:

  1. support references within batch requests
  2. support actions/functions in batch requests
  3. support bound actions/functions (3a. support ByD specific bound actions format)

Do I get this right? We will consider these requests, but I cannot give you any specific timeline. If you have any further input (e.g. ideas for an API, contributions) let me know.

carlonnheim commented 2 years ago

Hi @marikaner,

Yes, that is perfectly right! Thanks!

//Carl

fwilhe commented 1 year ago

Hi @carlonnheim

as a first step, support for OData v4 Bound Functions and Actions is implemented in version 2.11.0 of the sdk. See the updated docs section for info on how to use them.

I know this does not satisfy what you asked for yet, but maybe you'd like to see if this already helps you in any way or if you want to share feedback on how it works for you.

Best, Florian

carlonnheim commented 1 year ago

Hi @fwilhe, that sounds great, looking forward to try it out! Thanks! //Carl