etagsap-cloud-sdks4hana

Error while patching an inventory item with "API_PHYSICAL_INVENTORY_DOC_SRV" (eTag - CloudSDK)


we want to realize an inventory booking process in our Java application with the CloudSDK (Version 1.9.2). We are calling S4 OnPremise System (1709).

1.) we call the create process while using the service DefaultPhysicalInventoryDocumentService() with the method .createPhysInventoryDocHeader().

=> Result: Physical inventory document is created.

2.) The physical inventory objects for the created physical inventory document must be counted. For this we get the corresponding item with the method .getPhysInventoryDocItem(), set the new values and call an update procedure with the method updatePhysInventoryDocItem().

=>Result: Error: "The Data Service Request is required to be conditional. Try using the \"If-Match\" header."

We tried this process once with the Gateway Client from SAP. Here we have to access an instance with an GET process to get an "eTag" out of the response and to be able to specify it as an "If-Match" parameter in the patch method. This process works in the Gateway Client.

Nevertheless, we tried the same process with our Java application. Unfortunately, we do not get an eTag back for a Get Request. According to the trace in the back end, the same OData service is addressed as in the gateway client.

Our implementation is called via PostMan (for test purposes).

Request(Header/Body): Request - Header Request - Body

Response: Response

Patch - Method:

public void doPatch(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        ErpConfigContext config = new ErpConfigContext("ErpQueryEndpointHTTP");
        ErpEndpoint endpoint = new ErpEndpoint(config);

        String physDoc = request.getParameter("physicalInventoryDocument");

        String responseUpdate = null;
        PhysInventoryDocItem InvItem;

        BigDecimal quantity = new BigDecimal("25.000");

        try {

            DefaultPhysicalInventoryDocumentService invs = new DefaultPhysicalInventoryDocumentService();

            InvItem = invs
                    .getPhysInventoryDocItemByKey("2018", physDoc , "1")
                    .execute(endpoint);

            logger.info(InvItem.toString());


            InvItem.setQuantityInUnitOfEntry(quantity);
            InvItem.setUnitOfEntry("ST");
            InvItem.setFiscalYear("2018");
            InvItem.setPhysicalInventoryItemIsCounted(true);


                ODataUpdateResult patchResult = invs.updatePhysInventoryDocItem(InvItem).execute(endpoint);

                logger.info(patchResult.toString());

                responseUpdate = new Gson().toJson(patchResult);
                response.setStatus(HttpServletResponse.SC_CREATED);


        } catch (Exception e) {
            responseUpdate = e.getMessage();
            response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
            logger.error(e.getMessage(), e);

        }


        response.setContentType("application/json");
        response.getOutputStream().print(responseUpdate);

        logger.error(response.toString());

    }

Solution

  • As mentioned by Emdee, ETag handling is transparently supported during update requests since verion 1.10.0 of the SAP S/4HANA Cloud SDK.

    Version 2.0.0 of the SAP S/4HANA Cloud SDK in addition allows to set custom headers on all OData requests. You can use this for supplying the required ETag header also to a function import as follows:

    new DefaultPhysicalInventoryDocumentService()
                .postDifferences(...)
                .withHttpHeader("If-Match", document.getVersionIdentifier())
                .execute()
    

    Manually setting the header like this is only required for OData function imports, not for updating, where it is handled transparently as mentioned above.