If you are wondering how to send batch request in Android using the SMP 3.0 SDK SP05+, then this blog is for you.
A batch request allows a mobile client to send multiple operations in a single HTTP request. The following diagram represents the objects needed to create a batch request with SMP 3.0 native SDK for Android:
- The ODataRequestParamBatch class represents a batch request and it can contain 1 or more batch items.
- A batch item is represented by the ODataRequestBatchItem interface and the item can be single read request (ODataRequestParamSingle) or a change set (ODataRequestChangeSet).
- A change set (ODataRequestChangeSet) can contain only CUD requests and their execution is atomic (either all requests executed successfully, or all failed).

In order to use batch request, the mobile client need to:
1. Create a batch request
| Code snippet - Create Batch Request (ODataRequestParamBatch) |
|---|
| ODataRequestParamBatch requestParamBatch = new ODataRequestParamBatchDefaultImpl(); |
2. Create the batch item payload for CREATE and UPDATE operations.
| Code Snippet - Create Batch Item Payload (ODataEntity) |
|---|
ODataEntity newEntity = new ODataEntityDefaultImpl("RMTSAMPLEFLIGHT.Travelagency"); newEntity.getProperties().put("agencynum", new ODataPropertyDefaultImpl("agencynum", "12345678")); newEntity.getProperties().put("NAME", new ODataPropertyDefaultImpl("NAME", "Flight Center Inc")); newEntity.getProperties().put("STREET", new ODataPropertyDefaultImpl("STREET", "123 Main street")); ... |
3. Create a batch item and add item to the batch request
3.1 Single READ request
| Code Snippet - Create Batch Item: Single READ Request |
|---|
// Create batch item ODataRequestParamSingle batchItem = new ODataRequestParamSingleDefaultImpl(); batchItem.setResourcePath("TravelAgencies"); batchItem.setMode(ODataRequestParamSingle.Mode.Read); batchItem.setCustomTag("something to identify the request"); // Add batch item to batch request requestParamBatch.add(batchItem); |
3.2 Change set with UPDATE operation
| Code Snippet - Create Batch Item: Change Set |
|---|
// Create batch item ODataRequestParamSingle batchItem = new ODataRequestParamSingleDefaultImpl(); // Allocate OData Entity batchItem.setResourcePath("TravelAgencies(‘12345678’)"); batchItem.setMode(ODataRequestParamSingle.Mode.Update); batchItem.setCustomTag("something to identify the request"); batchItem.setPayload(newEntity); // Add headers Map<String, String> createHeaders = new HashMap<String, String>(); createHeaders.put("accept", "application/atom+xml"); createHeaders.put("content-type", "application/atom+xml"); batchItem.setOptions(createHeaders); // Create change set ODataRequestChangeSet changeSetItem = new ODataRequestChangeSetDefaultImpl(); // Add batch item to change set. // You can add more batch items to the same change set as long as they are CUD operations changeSetItem.add(batchItem); // Add batch item to batch request requestParamBatch.add(changeSetItem); |
4. Send Batch request: Batch requests are submitted as a single HTTP post request to the batch endpoint of a service. The HTTP status code of a batch response is generally “202 Accepted” and it only indicates that the overall request has been accepted for processing, not that every operation successfully completed. There will be a status code returned for each part of the multipart batch request.
| Code Snippet - Send Batch Request |
|---|
// Send request synchronously ODataResponse oDataResponse = odataStore.executeRequest(requestParamBatch); // Check http status response for batch request. // Status code should be "202 Accepted" Map<ODataResponse.Headers, String> headerMap = oDataResponse.getHeaders(); if (headerMap != null) { String code = headerMap.get(ODataResponse.Headers.Code); } // Get batch response if (oDataResponse instanceof ODataResponseBatchDefaultImpl) { ODataResponseBatch batchResponse = (ODataResponseBatch) oDataResponse; List<ODataResponseBatchItem> responses = batchResponse.getResponses(); for (ODataResponseBatchItem response : responses) { // Check if batch item is a change set if (response instanceof ODataResponseChangeSetDefaultImpl) { ODataResponseChangeSetDefaultImpl changesetResponse = (ODataResponseChangeSetDefaultImpl) response; List<ODataResponseSingle> singles = changesetResponse.getResponses(); for (ODataResponseSingle singleResponse : singles) { // Get Custom tag String customTag = singleResponse.getCustomTag(); // Get http status code for individual responses headerMap = singleResponse.getHeaders(); String code = headerMap.get(ODataResponse.Headers.Code); // Get individual response ODataPayload payload = singleResponse.getPayload(); if (payload != null) { if (payload instanceof ODataError) { ODataError oError = (ODataError) payload; String uiMessage = oError.getMessage(); } else { // TODO do something with payload } } } } else { // TODO Check if batch item is a single READ request } } } |
Questions? let me know,
I would also recommend looking at this document to understand how SAP Gateway deal with Batch requests
How To Batch Multiple Operations Into A Single Request
Troubleshooting Section: Testing batch request in a REST client in 3 steps
Testing the batch request from a REST client will help you discard any problems with the backend.
For more information about the REST client, visit SMP 3.0 : REST API Application Development
Step1: Onboard user and copy Application connection id from the response
Request: POST
URL: http://<server>:<port>/odata/applications/latest/<appid>/Connections
Headers
Content-Type: application/atom+xml
Authorization: Basic <encoded login and password>
Body
<?xml version="1.0" encoding="UTF-8"?>
<entry xml:base="http://localhost:8080/odata/applications/latest/com.sap.flight.kapsel/Connections"
xmlns="http://www.w3.org/2005/Atom" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata"
xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices">
<content type="application/xml">
<m:properties>
<d:DeviceType>Android</d:DeviceType>
</m:properties>
</content>
</entry>

Step2: Fetch CSRF Token
Request: GET
URL: http://<server>:<port>/<appid>/
Headers
Authorization: Basic <encoded login and password>
X-SMP-APPCID: <value received from step 1: onboard user>
X-CSRF-Token: Fetch
Step3: Send Batch request with two read operations
Request: POST
URL: http://<server>:<port>/<appid>/$batch
Headers
Content-Type: multipart/mixed; boundary=batch
Authorization: Basic <encoded login and password>
X-SMP-APPCID: <value received from step 1: onboard user>
X-CSRF-Token: <value received from step 2: fetch CSRF Token>
Body (mind the spacing between the --batch tags, it's very important)
--batch
Content-Type: application/http
Content-Transfer-Encoding: binary
GET CarrierCollection HTTP/1.1
--batch
Content-Type: application/http
Content-Transfer-Encoding: binary
GET TravelAgencies/?$filter= COUNTRY eq 'CA' HTTP/1.1
--batch--

Claudia