Пакетный запрос OData через службу подключения всегда возвращает 202 принятых

#sap-cloud-platform #sap-cloud-sdk #sap-cloud-foundry #sap-cloud-connector

#sap-облачная платформа #sap-cloud-sdk #sap-облако-литейное производство #sap-cloud-соединитель

Вопрос:

У нас есть приложение springboot / sap-cloud-sdk (3.34.1), развернутое на SAP CloudFoundry. Наше приложение подключается к встроенному шлюзу SAP для служб OData и использует службу назначения и подключения CF. В большинстве случаев это работает нормально. Недавно мы начали использовать пакетные запросы к нашей службе SAP OData.

Локальное тестирование на шлюзе SAP показывает, что пакетные запросы обрабатываются нормально. Мы получаем правильные результаты ошибок, когда отправляем запрос, который должен завершиться ошибкой, и когда мы отправляем правильный запрос, он также обрабатывается нормально.

Однако, когда мы развертываем приложение в SAP CF и запрос направляется через службу подключения, мы всегда получаем HTTP 202 Принятый ответ. Независимо от того, что возвращает шлюз SAP. Если мы выполняем некоторую отладку и трассировку на шлюзе SAP, мы видим ожидаемые поступающие запросы, а также ожидаемые ответы от шлюза SAP.

Похоже, что служба подключения каким-то образом не может передать ответы обратно в наше приложение.

введите описание изображения здесь

На рисунке выше показаны компоненты, через которые проходит запрос. Наше приложение PMD использует cloud sdk для создания пакетных запросов, определения адресата и отправки его через службу подключения на шлюз SAP. Шлюз возвращает правильный ответ, но мы никогда не видим этот ответ в нашем приложении. Вместо этого мы всегда получаем 202 принятых ответа.

— Обновление 2020-12-15 16:39 —

Мы используем OData V2. Мы провели еще несколько тестов, и это не служба подключения. Мы сосредоточились только на полезных нагрузках SAP Gateway для реагирования. Но, по-видимому, пакетные ответы всегда заключаются в 202 принятых ответа. Если мы посмотрим более внимательно, то увидим, что получаем следующий ответ:

 HTTP/1.1 202 Accepted

content-type: multipart/mixed; boundary=6C34B07793A6EA7C8AAFC5BC339BDAEC0
content-length: 709
dataserviceversion: 2.0
cache-control: no-cache, no-store, must-revalidate
sap-perf-fesrec: 1300458.000000

--6C34B07793A6EA7C8AAFC5BC339BDAEC0
Content-Type: application/http
Content-Length: 1171
content-transfer-encoding: binary

HTTP/1.1 400 Bad Request
Content-Type: application/json;charset=utf-8
Content-Length: 1050
dataserviceversion: 1.0

{"error":{"code":"ZCU/100","message":{"lang":"nl","value":"Service 0000000003 0000000010 niet gevonden voor operatie 0410"},"innererror":{"application":{"component_id":"","service_namespace":"/SAP/","service_id":"ZCU_PE_ORDER_SRV","service_version":"0001"},"transactionid":"23F2932D54040110E005FD84A23B406E","timestamp":"20201215151501.0634490","Error_Resolution":{"SAP_Transaction":"Run transaction /IWFND/ERROR_LOG on SAP Gateway hub system (System Alias ) and search for entries with the timestamp above for more details","SAP_Note":"See SAP Note 1797736 for error analysis (https://service.sap.com/sap/support/notes/1797736)","Batch_SAP_Note":"See SAP Note 1869434 for details about working with $batch (https://service.sap.com/sap/support/notes/1869434)"},"errordetails":[{"code":"ZCU/100","message":"Service 0000000003 0000000010 niet gevonden voor operatie 0410","propertyref":"","severity":"error","target":""},{"code":"/IWBEP/CX_MGW_BUSI_EXCEPTION","message":"Fout bij wijzigen PE order.","propertyref":"","severity":"error","target":""}]}}}
--6C34B07793A6EA7C8AAFC5BC339BDAEC0--
 

И каким-то образом содержимое ответа не читается должным образом SAP Cloud SDK.

В нашем коде мы отправляем 1 набор изменений с запросом. Следующие методы являются основой нашего пакетного вызова. batchUpdatePEOrderById Выполняет запрос. Другие методы являются просто помощниками для подготовки пакетного запроса.

Мы ожидали f.get(0) , что результаты первого набора изменений будут развернуты, или, по крайней мере, в нашем примере запрос приведет к Try.failure() , но это всегда приводит к Try.success()

 private Either<DomainError, ExternalId> batchUpdatePEOrderById(final ExternalId id, List<ServiceChange> serviceChanges, final String jwtToken) {
    final HttpDestination sapMatrix = httpDestinationProvider.providePrincipalPropagationDestination(jwtToken);

    // See https://sap.github.io/cloud-sdk/docs/java/features/odata/use-typed-odata-v2-client-in-sap-cloud-sdk-for-java#batch-requests
    var f = prepareBatchRequest(id, serviceChanges)
            .executeRequest(sapMatrix);
    return f.get(0).toEither()
            .bimap(error -> getDomainError(id, error), result -> {
                log.warn("Updated PE-Order {} successfully: {}", id, result.getCreatedEntities());
                return id;
            });
}

private ZCUPEORDERSRVServiceBatch prepareBatchRequest(ExternalId id, List<ServiceChange> serviceChanges) {
    var batch = peOrderService.batch();
    var changeSet = batch.beginChangeSet();
    // Split service changes and add to batch operation
    var newServices = mapServiceChanges(ChangeType.ADDED, serviceChanges, id);
    var updatedServices = mapServiceChanges(ChangeType.QUANTITY_CHANGED, serviceChanges, id);
    var deletedServices = mapServiceChanges(ChangeType.DELETED, serviceChanges, id);

    if (!newServices.isEmpty()) {
        buildServiceChangeSet(changeSet, newServices, ChangeType.ADDED);
    }

    if (!updatedServices.isEmpty()) {
        buildServiceChangeSet(changeSet, updatedServices, ChangeType.QUANTITY_CHANGED);
    }

    if (!deletedServices.isEmpty()) {
        buildServiceChangeSet(changeSet, deletedServices, ChangeType.DELETED);
    }
    return changeSet.endChangeSet();
}

private void buildServiceChangeSet(ZCUPEORDERSRVServiceBatchChangeSet changeSet, final List<Dienst> services, final ChangeType changeType) {
    switch (changeType) {
        case ADDED:
            services.forEach(changeSet::createDienst);
            break;
        case QUANTITY_CHANGED:
            services.forEach(changeSet::updateDienst);
            break;
        case DELETED:
            services.forEach(changeSet::deleteDienst);
            break;
        default:
            changeSet.endChangeSet();
    }
}
 

Есть какие-нибудь идеи, что здесь может быть не так?

Спасибо,

Дэнни

Комментарии:

1. Не могли бы вы рассказать, какой код вы используете для вызова пакетного запроса и является ли служба OData OData V2 или V4?

2. Я обновил свой вопрос дополнительной информацией.

3. И просто чтобы напомнить вам, правильно ли обрабатывается пакетный запрос SAP или нет. Кажется, что ошибка в обработке ответа в SDK

4. Глядя на код, похоже, что это ошибка в SDK. VDM просто никогда не проверяет, удалось ли выполнить отдельные запросы, а вместо этого напрямую пытается проанализировать отдельные результаты. Не могли бы вы, пожалуйста, проверить f.get(0).getCreatedEntities() , не выдает ли это ошибку?

5. @MatKuhr Я провел некоторое тестирование / отладку, используя сеанс удаленной отладки в SAP CF, установив точку останова return f.get(0).... . Нет f.get(0).getCreatedEntities , но есть только кот f.get(0).get().getCreatedEntities() . Это всегда приводит к списку из 0 записей. Также f.get(0).isSuccess() всегда true , даже если SAP отправляет ответ об ошибке в полезной нагрузке (например, в моем сообщении)

Ответ №1:

Эта ошибка исправлена в SAP Cloud SDK 3.34.1 .

Ознакомьтесь с соответствующими примечаниями к выпуску.

Комментарии:

1. Добавлена ссылка на примечания к выпуску SAP Cloud SDK 3.34.1 .

2. На основе sap.github.io/cloud-sdk/docs/java /… новая версия 3.36.0 должна была быть выпущена 4 дня назад. Однако он недоступен в maven central. Когда это будет доступно?

3. Теперь он доступен. Произошла необычная задержка при доставке библиотек в Maven Central.