【问题标题】:OData batch request through connectivity service always returns 202 Accepted通过连接服务的 OData 批量请求始终返回 202 Accepted
【发布时间】:2020-12-15 11:14:47
【问题描述】:

我们在 SAP CloudFoundry 上部署了一个 springboot/sap-cloud-sdk (3.34.1) 应用程序。我们的应用程序连接到用于 OData 服务的本地 SAP 网关,并使用 CF 目标和连接服务。在大多数情况下,这可以正常工作。 我们最近开始对我们的 SAP OData 服务使用批处理请求。

针对 SAP 网关的本地测试表明批处理请求得到了很好的处理。当我们发送一个应该失败的请求时,我们会得到正确的错误结果,当我们发送一个好的请求时,它也得到了很好的处理。

但是,当我们在 SAP CF 上部署应用程序并通过连接服务路由请求时,我们总是会收到 HTTP 202 Accepted 响应。无论 SAP 网关返回什么。如果我们在 SAP 网关上进行一些调试和跟踪,我们会看到预期的请求传入,也可以看到来自 SAP 网关的预期响应。

因此,连接服务似乎无法将响应传递回我们的应用程序。

上图展示了请求所经过的组件。我们的 PMD 应用程序使用云 sdk 创建批处理请求、解析目标并通过连接服务将其发送到 SAP 网关。网关返回正确的响应,但我们从未在我们的应用程序中看到该响应。相反,我们总是得到 202 Accepted 响应。

-- 2020-12-15 16:39更新--

我们使用的是 OData V2。我们进行了更多测试,但不是连接服务。我们只关注 SAP Gateway 的响应负载。但显然,批处理响应总是包含在 202 Accepted 响应中。如果我们仔细观察,我们会看到我们得到以下响应:

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();
    }
}

你有什么想法吗?

谢谢,

丹尼

【问题讨论】:

  • 能否分享一下您用于调用批处理请求的代码以及 OData 服务是 OData V2 还是 V4?
  • 我已经用额外的信息更新了我的问题。
  • 提醒您,SAP 是否正确处理了批处理请求。似乎是 SDK 中对响应的处理出了问题
  • 查看代码,看起来这是 SDK 中的一个错误。 VDM 根本不会检查单个请求是否成功,而是直接尝试解析单个结果。请检查f.get(0).getCreatedEntities() 是否产生错误?
  • @MatKuhr 我已经使用 SAP CF 上的远程调试会话在return f.get(0).... 上放置了一个断点进行了一些测试/调试。没有f.get(0).getCreatedEntities,只有f.get(0).get().getCreatedEntities()。这总是会产生一个包含 0 个条目的列表。同样f.get(0).isSuccess() 始终是true,即使 SAP 在有效负载中发送错误响应(就像我的帖子中的那个)

标签: sap-cloud-platform sap-cloud-sdk sap-cloud-foundry sap-cloud-connector


【解决方案1】:

自 SAP Cloud SDK 3.34.1 起,此错误已修复。

查看各自的release notes

【讨论】:

  • 添加了对 SAP Cloud SDK 发行说明3.34.1 的引用。
  • 基于sap.github.io/cloud-sdk/docs/java/…,新版本 3.36.0 应该在 4 天前发布。但是它在 maven Central 上不可用。什么时候可以使用?
  • 它现在可用。将库运送到 Maven Central 时出现了罕见的延迟。
猜你喜欢
  • 1970-01-01
  • 2022-12-20
  • 2019-09-01
  • 1970-01-01
  • 1970-01-01
  • 2019-08-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多