1

我们目前正在与 Batch Query 作斗争,这似乎忽略了由于错误的 URL 编码导致的 S4 端的过滤器表达式。

/sap/opu/odata/sap/ZP2M_A_CONTRACT_SEARCH_HDR_CDS/ZP2M_A_CONTRACT_SEARCH_HDR?$filter=PurchaseContractID eq %274600002020%27&$select=*&$format=json

使用返回的实体列表执行查询FluentHelperRead.execute(HttpClient) 包含只有一个实体的预期结果。


以批处理查询的形式执行查询,控制台中记录了以下请求:

GET ZP2M_A_CONTRACT_SEARCH_HDR?%24filter%3DPurchaseContractID+eq+%25274600002020%2527%26%24select%3D*%26%24format%3Djson HTTP/1.1

从所有批处理结果部分收集的列表包含所有实体。


看起来,查询 URL 的编码方式错误
,并且 S4 在以这种方式编码时忽略了过滤器表达式。
eg被 S4 忽略的$filter编码。%24filter

这似乎是BatchRequestImpl.getRequest(ODataQueryImpl)方法中的一个错误,
其中第二次对已编码的 URL 部分进行 URL 编码。

if(systemQuery.indexOf("$format=json&$count=true") != -1)
{
    systemQuery = systemQuery.substring(0, systemQuery.indexOf("$format=json&$count=true") -1);
    keysUrl.append("/$count");
}
systemQuery = URLEncoder.encode(systemQuery, "UTF-8"); // this code line which encodes the query 2nd time
keysUrl.append("?");

systemQuery = URLEncoder.encode(systemQuery, "UTF-8");位于
  BatchRequestImpl(1.38.0) - 第 295 行
  BatchRequestImpl(1.42.2) - 第 307 行的代码行
再次对 systemQuery 字符串进行编码(也包括 FilterExpression 的已编码部分)。

在调试器中撤消此代码行的更改并将 scapces 替换为 %20 或 '+' 时,批处理查询看起来像这样

GET ZP2M_A_CONTRACT_SEARCH_HDR?$filter=PurchaseContractID%20eq%20%274600002020%27&$select=*&$format=json HTTP/1.1

GET ZP2M_A_CONTRACT_SEARCH_HDR?$filter=PurchaseContractID+eq+%274600002020%27&$select=*&$format=json HTTP/1.1

它返回预期的结果(正好是 1 个实体)。


使用这些库版本时出现此错误编码:
sdk-bom: 3.16.1
连接性:1.38.0

此问题也出现在最新的 SDK 版本中:
sdk-bom: 3.21.0
连接性:1.39.0

这个问题也出现在最新版本的连接 JAR 中:
sdk-bom: 3.21.0
connectivity: 1.40.2

与 ABAP/S4 同事一起调试发现
,S4 仅应用过滤器表达式,如果$filter在请求中找到关键字,
%24filter%3D则会被忽略(我们让所有实体运行 Batch Query 的原因)。

我解决它的建议是

// decode query first (to decode the filter expression)
systemQuery = URLDecoder.decode(systemQuery, "UTF_8");
// encode query
systemQuery = org.apache.commons.httpclient.util.URIUtil.encodeQuery(systemQuery, "UTF_8");

我的代码,我如何调用batchRequest:

FluentHelperRead<?, MyEntity, ?> queryApi = myService.getAll... // with adding some filter expression

BatchRequestBuilder batchRequestBuilder = BatchRequestBuilder.withService(MyService.DEFAULT_SERVICE_PATH);
ODataQuery query = queryApi.toQuery();
batchRequestBuilder.addQueryRequest(query);
HttpClient httpClient = HttpClientAccessor
    .getHttpClient(DefaultErpHttpDestinationAccessor.get());
BatchRequest request = batchRequestBuilder.build();
BatchResult result = request.execute(httpClient);
// ... evaluate response

我认为,这是 Cloud SDK 中的普遍问题。
是否有可能在下一个 Cloud SDK 版本中修复此问题?

4

2 回答 2

1

这已在依赖项中修复,并且从版本开始3.25.0,SAP Cloud SDK 包含该修复。

于 2020-07-31T10:58:13.823 回答
1

你能分享你的批量请求代码吗?你BatchRequestImpl直接用吗?

问题是 SAP Cloud SDK 依赖于一些依赖项,其中一个引入了BatchRequestImpl,如果直接调用它,则错误在依赖项方面。我已经通知他们调查这个双重编码问题。不幸的是,我们不能直接影响它的解决速度,有时它需要的时间比我们想要的要长。

好消息是,我们正在努力用我们自己的实现替换这种依赖关系,以解决这类问题。这batch是正在进行的工作,应该在Beta下个月底左右提供 OData V4,希望大约在同一时间提供 OData V2(这不是一个硬性承诺,取决于其他优先事项)。

从这里开始,我们必须等待首先发生的事情:

  • 该错误已在依赖项侧修复
  • 内部 OData 客户端实现与Batch一起准备就绪

我希望它能帮助并解释当前的解决方案路径。如果您分享一些关于您的截止日期和潜在影响的信息,我们将很乐意考虑这一点。

于 2020-06-24T15:13:49.530 回答