Inkers
Inkers

Reputation: 219

Handling of etags in batch request using SAP Cloud SDK

I am trying to carry out a batch request including a create, update and a delete (all are different salesorders). As per this question here which deals with something similar, I have done a get for the items I want to update and delete before I add them to the batch request. I am using the SalesOrder.builder() to prepare the SalesOrder I want to create.

 final ErpHttpDestination destination = DestinationAccessor.getDestination(DESTINATION_NAME)
                                    .asHttp().decorate(DefaultErpHttpDestination::new);

                    final SalesOrderItem salesOrderItem1 = SalesOrderItem.builder().material(material)
                                    .requestedQuantityUnit(requestedQuantityUnit).build();

                    final SalesOrder salesOrder1 = SalesOrder.builder().distributionChannel(distributionChannel)
                                    .salesOrderType(salesOrderType).salesOrganization(salesOrganization)
                                    .organizationDivision(organizationDivision).soldToParty(soldToParty)
                                    .item(salesOrderItem1).build();

                    final SalesOrder orderToUpdate = new GetSingleSalesOrderCommand(orderToUpdateID, destination,
                                    new DefaultSalesOrderService()).execute();
                    orderToUpdate.setSoldToParty(updateSoldToParty);

                    final SalesOrder orderToDelete = new GetSingleSalesOrderCommand(orderToDeleteID, destination,
                                    new DefaultSalesOrderService()).execute();

                    SalesOrderServiceBatch service = new DefaultSalesOrderServiceBatch(
                                    new DefaultSalesOrderService());

                    BatchResponse bRes = service.beginChangeSet().createSalesOrder(salesOrder1).updateSalesOrder(orderToUpdate)
                                    .deleteSalesOrder(orderToDelete).endChangeSet().execute(destination);

I am then logging the BatchResponse and see I am getting a Batch Response Failure:

eTag handling not supported for http method 'POST'

I have searched for this error but can't find any resolution to it. Any ideas? Thanks.

UPDATE: Increasing the logging to DEBUG I can see the batch request that is being sent and can see that there is an if-match header being added to the create request, which doesn't make sense as it can't match something that doesn't exist yet.

 "msg":"--batch_123\r\nContent-Type: multipart/mixed; 
 boundary=changeset_(changeset number)\r\n\r\n--
 changeset_(changeset number)\r\nContent-Type: 
 application/http\r\nContent-Transfer-Encoding: binary\r\n\r\nPOST 
 /sap/opu/odata/sap/API_SALES_ORDER_SRV/A_SalesOrder HTTP/1.1\r\nContent- 
 Length:
193\r\nIf-Match: W/\"datetimeoffset'2020-05- 
 01T11%3A51%3A16.8631720Z'\"\r\nAccept: 
 application/json;odata=verbose\r\nContent-Type:......

The I get the error:

  Inner Error:
 "msg":"batch 
  responseFailure(com.sap.cloud.sdk.odatav2.connectivity.ODataException: 
  null: <?xml version=\"1.0\" encoding=\"utf-8\"?><error 
  xmlns=\"http://schemas.microsoft.com/ado/2007/08/dataservices/metadata\"> 
  <code>/IWFND/CM_MGW/537</code><message xml:lang=\"en\">eTag handling not 
  supported for http method 'POST'</message><innererror>...

However, what does work is if I wrap each request in its own changeset e.g.

 service
 .beginChangeSet().createSalesOrder(order).endChangeSet()
 .beginChangeSet().updateSalesOrder(orderToUpdate).endChangeSet()
 .beginChangeSet().deleteSalesOrder(orderToDelete).endChangeSet()
 .execute(destination);

Upvotes: 0

Views: 963

Answers (2)

MatKuhr
MatKuhr

Reputation: 563

Edit:

This is fixed as of version 3.25.0.


Initial Answer:

This seems to be a bug. I was able to reproduce this with a different service and the behaviour is the same: The if-match header is incorrectly applied to the POST operation as well.

When debugging it seems like the request is build up correctly with the header only being present on update and delete. However, it seems that when the batch request is serialised to JSON it gets added to all requests.

So until this is fixed the workaround is isolating these operations via change sets, as you already pointed out.

Upvotes: 1

Alexander D&#252;mont
Alexander D&#252;mont

Reputation: 938

Looks like eTag handling is not supported for your endpoint.

Now you can do the following to omit eTag headers:

orderToUpdate.setVersionIdentifier(null); 
orderToDelete.setVersionIdentifier(null);

However I'm not sure how 'POST' fits the error description, because update uses PATCH and delete uses DELETE. The only POST that I expect would be coming from create. But we do not add headers for entity version identifiers (eTag) in OData create operation. If the same error still comes up, please try again without running createSalesOrder(salesOrder1).

Upvotes: 0

Related Questions