SAP / cloud-sdk

The SAP Cloud SDK documentation and support repository.
https://sap.github.io/cloud-sdk/
Apache License 2.0
45 stars 43 forks source link

Documentation for accessing batch responses appears to be outdated #620

Closed WorkAccountM closed 2 years ago

WorkAccountM commented 2 years ago

Hello, I am using the SAP Cloud SDK for Java for Batch Requests. In this case for SalesOrders. In the documentation (https://sap.github.io/cloud-sdk/docs/java/features/odata/use-typed-odata-v4-client-in-sap-cloud-sdk-for-java) I see something like this:

GetByKeyRequestBuilder<BusinessPartner> getBusinessPartnerByKey = ...
CreateRequestBuilder<BusinessPartner> createBusinessPartnerRequest1 = ...
CreateRequestBuilder<BusinessPartner> createBusinessPartnerRequest2 = ...
DeleteRequestBuilder<BusinessPartner> deleteBusinessPartnerRequest = ...

BatchResponse result =
    service
        .batch()
        .addReadOperations(getBusinessPartners, getBusinessPartnerByKey)
        .addChangeset(createBusinessPartnerRequest1, createBusinessPartnerRequest2, deleteBusinessPartnerRequest)
        .execute(destination);

Now I seem to be unable to find this request builder. I can create an instance via its constructor but it needs a different VdmEntity than the SalesOrder I am using. It needs com.sap.cloud.sdk.datamodel.odatav4.core.VdmEntity instead of com.sap.cloud.sdk.datamodel.odata.helper.VdmEntity. I was only able to do it this way:

var changeSet = salesOrderService.batch()
                .beginChangeSet()
                .updateSalesOrder(salesOrderRequest.getSalesOrder())
                .updateSalesOrderItem(salesOrderRequest.getSalesOrderItem())
                .endChangeSet()
                .executeRequest(destination)
                .get(0) // Lets pretend I checked everything, just to shorten the example
                .get();

This creates an instance of a com.sap.cloud.sdk.datamodel.odata.helper.batch.BatchResponseChangeSet. I would however want to make use of the com.sap.cloud.sdk.datamodel.odatav4.core.BatchResponse, that you mention inside the documentation.

Now for my use case I basically have to replace the entire SalesOrder. It is possible that new SalesOrderItems are added as a result, because the newer version of the SalesOrder contains more than before. Since I also have to map these SAP entities to our own master data, I would like to keep the hierarchy intact. This would be easier, if I could make use of the "com.sap.cloud.sdk.datamodel.odatav4.core.BatchResponse.getModificationResult" method inside the documentation. Then I could easily send the hierarchy of requests for a SalesOrder as one changeset and recreate the hierarchy for the responses. I would prefer to be able to just use the Update Method of SalesOrderService together with "replacingEntity" for the whole deeply nested object but sadly this doesn't work (I know that this would mean the SDK would have to create multiple requests).

Because of the differences in VdmEntity I might just be getting some imports wrong but I basically followed https://sap.github.io/cloud-sdk/docs/java/getting-started

Best Regards

Cloud SDK Info:

<dependency>
            <groupId>com.sap.cloud.sdk.s4hana</groupId>
            <artifactId>s4hana-api-odata-onpremise</artifactId>
            <version>${sap.version}</version>
        </dependency>
        <dependency>
            <groupId>com.sap.cloud.sdk.s4hana</groupId>
            <artifactId>s4hana-api-odata-v4-onpremise</artifactId>
            <version>${sap.version}</version>
        </dependency>
        <dependency>
            <groupId>com.sap.cloud.sdk.s4hana</groupId>
            <artifactId>s4hana-connectivity</artifactId>
            <version>${sap.version}</version>
        </dependency>
        <dependency>
            <groupId>com.sap.cloud.sdk.s4hana</groupId>
            <artifactId>s4hana-core</artifactId>
            <version>${sap.version}</version>
        </dependency>
<sap.version>3.59.0</sap.version>
newtork commented 2 years ago

I assume you mean the OData v2 service SalesOrderService.

This is incompatible with request builder classes for OData v4. Hence you cannot apply the logic described in the linked documentation page. (We do plan to migrate the v2 API to v4 API with one of the next major releases, but there is no schedule yet.)

If you want to access all batch response elements in OData v2 as of today, I see three options for you:

  1. Cast OData v2 Client API to Generic OData Client:

    HttpDestination destination;
    SalesOrderServiceBatch batchRequest;
    HttpClient httpClient = HttpClientAccessor.getHttpClient(httpClient);
    
    ODataRequestResultMultipartGeneric response = batchRequest.toRequest().execute(httpClient);
    
    // extract second response-set, first response part
    HttpResponse httpResponse_1_0 = response.getBatchedResponses().get(1).get(0);
    
    // optionally serialize to String
    String httpPayload_1_0 = EntityUtils.toString(httpResponse_1_0.getEntity(), StandardCharsets.UTF_8)

    You have to take care of deserialization yourself.

  2. Mix OData v2 Client API to Generic OData Client:

    HttpDestination destination;
    SalesOrderService service;
    String servicePath = SalesOrderService.DEFAULT_SERVICE_PATH;
    HttpClient httpClient = HttpClientAccessor.getHttpClient(destination);
    
    ODataRequestRead read = service.getAllSalesOrder() /* ...*/ .toRequest();
    ODataRequestUpdate update = service.updateSalesOrder( salesOrder ).toRequest();
    
    ODataRequestResultMultipartGeneric response = new ODataRequestBatch(servicePath, ODataProtocol.V2)
     .addRead(read)
     .beginChangeset()
     .addUpdate(update)
     .endChangeset()
     .execute(httpClient);
    
    List<SalesOrder> entities = response.getResult(read).asList(SalesOrder.class);
    int httpCode = response.getResult(update).getHttpResponse().getStatusLine().getStatusCode();

    Feel free to explore the API. Please understand this is the "expert" API with less convenience than OData v4 API.

  3. Only use Generic OData Client: See documentation to construct requests without additional convenience.

WorkAccountM commented 2 years ago

Thank you for the quick response and helpful information regarding v2 vs v4. I'll try the options out that you mentioned and see which one makes the most sense for my use case.

Best Regards