依赖的Web客户端调用 – Spring响应式

huangapple go评论84阅读模式
英文:

Dependant webclient calls - Spring Reactive

问题

以下是你提供的代码段的翻译部分:

@Autowired
Issue issue;

List<Issue> issueList = new ArrayList<>();

public Mono<Response> getResponse(Request request) {
   return webClient.post()
     .uri("myURI")
     .body(Mono.just(request), Request.class)
     .retrieve()
     .bodyToMono(Response.class)
     .flatMap(resp -> {
           resp.getIssues().stream()
              .forEach(issueTemp -> {
                 issue = issueTemp;
                 webClient.get()
                    .uri("mySecondURI" + issueTemp.getId())
                    .retrieve()
                    .bodyToMono(Issue.class)
                    .flatMap(issueTemp2 -> {
                        issue.setSummary(issueTemp2.getSummary());
                        return Mono.just(issue);
                    }).log();
           issueList.add(issue);
        });

        Response responseFinal = new Response();
        responseFinal.setIssues(issueList);
        return Mono.just(responseFinal);
    }).log();
}

**UPDATE 2:**

I have changed my code to Functions and used Flux instead of stream iterations. What I am facing now is, all the iterations are filtered out in the doSecondCall method. Please refer to my comment in the doSecondCall method. Due to this, the second call is not triggered. If I don't apply the filter, there are requests triggered like "issue/null," which also causes my service to go down.

public Mono<Response> getResponse(Request request) {
   return webClient.post()
     .uri("myURI")
     .body(Mono.just(request), Request.class)
     .retrieve()
     .bodyToMono(Response.class)
     .flatMap(r ->
         doSecondCall(r).flatMap(issueList -> {
             r.setIssues(issueList);
             return Mono.just(r);
           })
     );
}

public Mono<Issue> doSecondCall(Response r) {
    return Flux.fromIterable(r.getIssues())
               .filter(rf -> rf.getId() != null) // everything gets filtered out
               .flatMap(issue -> getSummary(issue.getId()))
               .collectList();
}

public Mono<Issue> getSummary(Response r) {
    return webClient.get()
                   .uri("issue/" + id)
                   .retrieve()
                   .bodyToMono(Issue.class).log();
}

[链接 https://stackoverflow.com/questions/53112634/how-does-reactive-programming-using-webflux-handles-dependent-external-api-calls] @Thomas- 也发现了这个线程。他基本上说,除非阻塞第一个调用,否则无法声明第二个调用。这是真的吗?

注意:由于你要求只返回翻译好的部分,我已经过滤掉了其他内容。如果你有进一步的问题或需要解释,请随时提问。

英文:

I am trying to do two API calls, the second API call is dependent on the first API response. The following piece of code gives response for first weblient call.Here I am not getting the response from second API call. On log I could see that the request for the second webclient call is not even started with onSubscribe(). Can you please tell me what mistake am I doing.

@Autowired
Issue issue;
List issueList = new ArrayList&lt;&gt;();
public Mono&lt;Response&gt; getResponse(Request request) {
return webClient.post()
.uri(&quot;myURI&quot;)
.body(Mono.just(request),Request.class)
.retrieve()
.bodyToMono(Response.class)
.flatMap(resp-&gt;{
resp.getIssues().stream()
.forEach(issueTemp -&gt; {
issue = issueTemp;
webClient.get()
.uri(&quot;mySecondURI&quot; + issueTemp.getId())
.retrieve()
.bodyToMono(Issue.class)
.flatMap(issueTemp2-&gt; {
issue.setSummary(issueTemp2.getSummary());
return Mono.just(issue);
}).log();
issueList.add(issue);
});
Response responseFinal = new Response();
responseFinal.setIssues(issueList);
return Mono.just(responseFinal);
}).log();
}

UPDATE 2:

I have changed my code to Functions and used Flux instead of stream iterations.What I am facing now is , all the iterations are get filtered out in doSecondCall method. Please refer my comment in doSecondCall method. Due to which the second call is not triggered. If i dont apply the filter, there are requests triggered like "issue/null" which also causes my service to go down.

 public Mono&lt;Response&gt; getResponse(Request request) {
return webClient.post()
.uri(&quot;myURI&quot;)
.body(Mono.just(request),Request.class)
.retrieve()
.bodyToMono(Response.class)
.flatMap(r-&gt;
doSecondCall(r).flatMap(issueList-&gt;{
r.setIssues(issueList);
return Mono.just(r);
})
);
}
public Mono&lt;Issue&gt; doSecondCall(Response r) {
return Flux.fromIterable(r.getIssues())
.filter(rf-&gt;rf.getId()!=null) //everything gets filtered out
.flatMap(issue-&gt;getSummary(issue.getId()))
.collectList();
}
public Mono&lt;Issue&gt; getSummary(Response r) {
return webClient.get()
.uri(&quot;issue/&quot;+id)
.retrieve()
.bodyToMono(Issue.class).log();
}

[ https://stackoverflow.com/questions/53112634/how-does-reactive-programming-using-webflux-handles-dependent-external-api-calls ] @Thomas- Also ,Just found this thread. He basically says unless you block the first call, there is no way to declare the second one. Is that the case?

答案1

得分: 3

你没有触发第二个调用的原因是因为你在这个答案中提到的地方中断了链式调用(带有示例)。

停止中断链式调用

// 这里...
.forEach(issueTemp -&gt; {
issue = issueTemp; // 而这只是愚蠢的?为什么?
webClient.get() // 在这里,你调用了 webClient 但忽略了返回值,所以你中断了链式调用。
.uri(&quot;mySecondURI&quot; + issueTemp.getId())
.retrieve()
.bodyToMono(Issue.class)
.flatMap(issueTemp2-&gt; {
issue.setSummary(issueTemp2.getSummary());
return Mono.just(issue); // 在这里返回,但你忽略了这个返回值。
}).log();
issueList.add(issue);
});

你应该使用更多的函数来拆分你的代码。通过编写一个函数并始终从返回语句开始,养成习惯。你的代码很难阅读。

我认为你应该使用 Flux 来代替迭代流。

// 类似下面这样,我是手写的,没有使用IDE
// 我不知道你的逻辑是什么样的,但你应该能明白我的意思。
Flux.fromIterable(response.getIssues())
.flatMap(issue -&gt; {
return getIssue(issue.getId())
.flatMap(response -&gt; {
return issue.setSummary(reponse.getSummary());
});
}).collectList();
英文:

Why you are not triggering the second calls is because you are breaking the chain as i have mentioned in this answer (with examples).

Stop breaking the chain

// here...
.forEach(issueTemp -&gt; {
issue = issueTemp; // and this is just silly? why?
webClient.get() // Here you are calling the webClient but ignoring the return value, so you are breaking the chain.
.uri(&quot;mySecondURI&quot; + issueTemp.getId())
.retrieve()
.bodyToMono(Issue.class)
.flatMap(issueTemp2-&gt; {
issue.setSummary(issueTemp2.getSummary());
return Mono.just(issue); // Return here but you are ignoring this return value
}).log();
issueList.add(issue);
});

You should use more functions to divide up your code. Make it a habit by writing a function and always start with the return statement. You code is very hard to read.

I think you should instead use a FLux instead of iterating a stream.

// something like the following i&#39;m writing by free hand without IDE
// i have no idea what your logic looks like but you should get the point.
Flux.fromIterable(response.getIssues())
.flatMap(issue -&gt; {
return getIssue(issue.getId())
.flatMap(response -&gt; {
return issue.setSummary(reponse.getSummary());
});
}).collectList();

huangapple
  • 本文由 发表于 2020年5月4日 16:24:42
  • 转载请务必保留本文链接:https://go.coder-hub.com/61587970.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定