Warm tip: This article is reproduced from serverfault.com, please click

Odata Query Batch Request

发布于 2021-01-14 13:19:52

We are using SAP SDK 3.25.0 and calling a batch request Read query passing some filters. I am getting the response of all the records and it can be seen that the filter is not working properly.

I have referred this blog here but I am getting the same issue of decode URL issue YY1_QuantityContractTracki?$filter=((CustomerName eq %27Ford%27) and (SalesSchedulingAgreement eq %270030000141%27)) and (PurchaseOrderByCustomer eq %27TEST%27)&$select=SalesSchedulingAgreement,PurchaseOrderByCustomer,Customer,CustomerName,SalesSchedulingAgreementItem,Material,MaterialByCustomer&$format=json

Below is the query program which I am using.

Am I missing something here. Please let us know Thanks, Arun Pai

final BatchRequestBuilder builder = BatchRequestBuilder.withService("/sap/opu/odata/sap/YY1_QUANTITYCONTRACTTRACKI_CDS");
    for (Contract contract : contracts) {
        FilterExpression mainFilter = new FilterExpression("CustomerName", "eq", ODataType.of(contract.getCustomerName()))
                .and(new FilterExpression("SalesSchedulingAgreement", "eq", ODataType.of(contract.getSchAgrmntNo())))
                .and(new FilterExpression("PurchaseOrderByCustomer", "eq", ODataType.of(contract.getCustRefNo())));
        final ODataQuery oDataQuery = ODataQueryBuilder
                .withEntity(sapConfig.getEssentialsContractServiceUrl(),
                        sapConfig.getEssentialsContractListEntity())
                .select("SalesSchedulingAgreement", "PurchaseOrderByCustomer", "Customer", "CustomerName",
                        "SalesSchedulingAgreementItem", "Material", "MaterialByCustomer")
                .filter(mainFilter)
                .build();
        builder.addQueryRequest(oDataQuery);
    }
    final BatchRequest batchRequest = builder.build();
    final BatchResult batchResult = batchRequest.execute(httpClient);

Update

I have changed the version to 3.35.0 today with connectivity version 1.40.11 but it did'nt work either. Below is the log request which gets printed in the console


2021-01-15 19:15:03.831 INFO 42640 --- [io-8084-exec-10] c.s.c.s.o.c.impl.BatchRequestImpl : --batch_123 Content-Type: application/http Content-Transfer-Encoding: binary

GET YY1_QuantityContractTracki?%24filter%3D%28%28CustomerName+eq+%2527Ford27%29+and+%28SalesSchedulingAgreement+eq+%25270030000141%2527%29%29+and+%28PurchaseOrderByCustomer+eq+%2527TEST%2527%29%26%24select%3DSalesSchedulingAgreement%2CPurchaseOrderByCustomer%2CCustomer%2CCustomerName%2CSalesSchedulingAgreementItem%2CMaterial%2CMaterialByCustomer%26%24format%3Djson HTTP/1.1 Accept: application/json;odata=verbose

--batch_123--

Questioner
Arun Kumar
Viewed
0
Alexander Dümont 2021-03-22 18:01:21

Update (22.03.2021)

With the release of SAP Cloud SDK 3.41.0 this week we'll enable support for read operations in OData batch requests on the type-safe API. Please find the chapter in the respective documentation. Example:

BusinessPartnerService service;
BusinessPartnerAddress addressToCreate1;
BusinessPartnerAddress addressToCreate2;

BusinessPartnerFluentHelper requestTenEntities = service.getAllBusinessPartner().top(10);
BusinessPartnerByKeyFluentHelper requestSingleEntity = service.getBusinessPartnerByKey("bupa9000");

BatchResponse result =
    service
        .batch()
        .addReadOperations(requestTenEntities)
        .addReadOperations(requestSingleEntity)
        .executeRequest(destination);

List<BusinessPartner> entities = result.getReadResult(requestTenEntities);
BusinessPartner entity = result.getReadResult(requestSingleEntity);

Original response:

I'm from the SAP Cloud SDK team. Generally we recommend our users to generate classes for their OData service interactions. This way you can easily make sure that requests are according to specification, while type safety is taken care of.

Unfortunately I cannot help you with the API of BatchRequestBuilder, BatchRequest or BatchResult because they are not directly a part of SAP Cloud SDK and not maintained by us. Instead we suggest our own request builders.


If the generation of classes, as linked above, is not an option for you, then I would suggest to try our expert API featuring the Generic OData Client of SAP Cloud SDK. This is the code that we would also use internally for our generated request builders:

String servicePath = "/sap/opu/odata/sap/YY1_QUANTITYCONTRACTTRACKI_CDS";
ODataRequestBatch requestBatch = new ODataRequestBatch(servicePath, ODataProtocol.V2);
Map<Contract, ODataRequestRead> batchedRequests = new HashMap<>();

// iterate over contracts, construct OData query objects and add them to the OData batch request builder
for (Contract contract : contracts) {
    String entityName = sapConfig.getEssentialsContractListEntity();
    String serviceUrl = sapConfig.getEssentialsContractServiceUrl();
    StructuredQuery structuredQuery = StructuredQuery.onEntity(entityName, ODataProtocol.V2);

    structuredQuery.select("SalesSchedulingAgreement", "PurchaseOrderByCustomer", "Customer", "CustomerName", "SalesSchedulingAgreementItem", "Material", "MaterialByCustomer");
    structuredQuery.filter(FieldReference.of("SalesSchedulingAgreement").equalTo(contract.getSchAgrmntNo()));
    structuredQuery.filter(FieldReference.of("PurchaseOrderByCustomer").equalTo(contract.getCustRefNo()));

    String encodedQuery = structuredQuery.getEncodedQueryString();
    ODataRequestRead requestRead = new ODataRequestRead(serviceUrl, entityName, encodedQuery, ODataProtocol.V2);
    batchedRequests.put(contract, requestRead);
    requestBatch.addRead(requestRead);
}

// execute the OData batch request
ODataRequestResultMultipartGeneric batchResult = requestBatch.execute(httpClient);

// extract information from batch response, by referring to the individual OData request references
for( Map.Entry<Contract, ODataRequestRead> requestMapping : batchedRequests.entrySet() ) {
    ODataRequestResultGeneric queryResult = batchResult.getResult(requestMapping.getValue());
    List<Map<String, Object>> itemsForQuery = queryResult.asListOfMaps();
}

Kind regards

Alexander