How can I do a file upload during an OData Batch Request and still maintain proper transaction security? So the goal is to have "all or nothing" saved on the backend, which is typically realized by wrapping the actual requests into a ChangeSet.
We are using SAPUI5/OpenUI5 1.36.8 and SAP GW on NW 7.5 SP02. Furthermore, we are using a Component based app with sap.ui.model.odata.v2.ODataModel and batch requests are enabled.
Let's assume we have an Entity Employee + Photo, as well as the corresponding EntitySets Employees + Photos. Furthermore, we have a navigation Property "Photo" from Employee to Photo (1 to 0..1 Relation) and every employee has a 1 to 1 relation to an Address Entity. In other words, the following is possible:
GET: /Employees('123') ==> returns the Employee data, i.e. firstName GET: /Employees('123')/Photo ==> returns the Entity data, i.e. uploadedOn GET: /Employees('123')/Photo/$value ==> returns the file content, i.e. a jpg file GET: /Employees('123')/Address ==> returns the address data, i.e. street,...
Next, let's assume I have an app to add new employees. The app offers several pages/screens to fill the Employee data, the address, and to choose a file. Everything happens on the front end only, until the user presses the save button in the end. Until this happens, no data is sent to the backend. When the save button is pressed "all or nothing" should be saved on the backend. In other words, An Employee Entity is created, an related Address Entity is created, a related Photo Entity is created, and a corresponding File is uploaded. If any of these fails, then the backend should "rollback".
One way to achieve this is creating a deep entity (although deep creates are not supported and may not work). However, how can I make sure that even the file upload via sap.ui.unified.FielUploader is in the same create deep entity request (and ChangeSet) in order to make sure that "all or nothing" is fulfilled?
In fact, sap.ui.model.odata.v2.ODataModel does not support OData Streams, so something like createStream(), deleteStream(), updateStream(), or readStream() is not available in the v2.ODataModel. Creating deep entities together with the file content in one request is also not supported. At the same time the sap.ui.unified.FielUploader always sends POST requests - using a different HTTP METHOD (i.e. PUT) is not possible because it's hard coded. The FileUploader has no special support for the ODataModel and/or OData Streams, it basically only needs the upload URL and that's it.
So my next question is (slightly different then the one from above):
How can I put a CREATE STREAM or UPDATE STREAM (= File Upload via POST or File Upload via PUT) into a batch request containing other changes as well (all in one change set) to achieve the "all or nothing" approach? Of course, this would not work in all browsers because I would have to access the file's binaries...
If this is not possible out of the box (and I'm pretty sure of this) then the workaround is very "hacky" and might include special handling on both front end and backend, right? I want to avoid modifying the UI5 libs, i.e. extending the batch request handling, adding support of PUT to the FileUploader, etc. How do you achieve transaction security in such cases, what are the best practices? Or is there anything I'm missing?
Hint:
To make SAP GW accept a POST (Create) on a Navigation property we have to tweak the relationships on GW, for details see https://scn.sap.com/thread/3592469 and http://scn.sap.com/thread/3580538