我们目前正在与 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 版本中修复此问题?