You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

添加thenApply嵌套后出现CompletionStage类型转换错误的原因咨询

Error: incompatible types in lambda return type (Response vs CompletionStage<Response>)

Let's break down why this error popped up after your code change, and how to fix it.

The Root Cause

Your original code used thenApply on the accountServiceClient.getAccount() future, which worked because the lambda inside thenApply returned a direct Response<ByteString> object, resulting in a clean CompletionStage<Response<ByteString>> that matched your method's return type.

After adding the inner httpClient.send(...).thenApply(...) call, the lambda in your outer thenApply now returns a CompletionStage<Response<ByteString>> instead of a plain Response<ByteString>. This turns the entire chain into:

CompletionStage<CompletionStage<Response<ByteString>>>

This nested type doesn't match your method's declared return type, and the exceptionally lambda is still trying to return a Response<ByteString> (from checkExceptionCauses), which clashes with the nested stage's expected type.

Fix 1: Replace outer thenApply with thenCompose

thenCompose is made exactly for cases where your lambda returns another CompletionStage—it automatically "flattens" nested stages into a single CompletionStage<T> instead of CompletionStage<CompletionStage<T>>.

Here's the adjusted code:

private CompletionStage<Response<ByteString>> getAccountById(RequestContext rc) {
    return accountServiceClient.getAccount()
        // Swap thenApply for thenCompose here
        .thenCompose(getAccountResponse -> {
            AdAccountResponse payload;
            payload.map(getAccountResponse);
            
            Request salesforceRequest = Request.forUri(FORCEIT_GET_BUSINESS_INFO_URI, "GET")
                .withPayload(businessInfoRequestPayload);
            
            return httpClient.send(salesforceRequest, rc)
                .thenApply(salesforceResponse -> {
                    if (salesforceResponse.payload().isPresent()) {
                        // ... your existing logic ...
                    } else {
                        // ... your existing logic ...
                    }
                    AdAccountResponse payload;
                    payload.map(getAccountResponse);
                    return Response.forPayload(serializePayload(payload));
                });
        })
        .exceptionally(exception -> {
            LOG.error("Lorem ipsum");
            // Now this returns Response<ByteString>, which matches the flattened stage's generic type
            return checkExceptionCauses(exception);
        });
}

Why This Works

  • thenCompose merges the inner CompletionStage<Response<ByteString>> into the parent stage, resulting in a top-level CompletionStage<Response<ByteString>> that perfectly matches your method's return type.
  • The exceptionally lambda can now safely return Response<ByteString> (from checkExceptionCauses) because the upstream stage's generic type is no longer nested.

Why Your Initial Fix Didn't Work

When you tried wrapping checkExceptionCauses in CompletableFuture.completedFuture(), you addressed the exceptionally type mismatch but didn't fix the outer nested stage issue. The outer thenApply was still producing a CompletionStage<CompletionStage<Response<ByteString>>>, which doesn't align with your method's return type. Using thenCompose resolves both problems in one step.

内容的提问来源于stack exchange,提问作者Andrew Cheong

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 07:25:41