Reputation: 105
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<>();
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 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<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();
}
[ 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?
Upvotes: 1
Views: 4647
Reputation: 14820
Why you are not triggering the second calls is because you are breaking the chain as i have mentioned in this answer (with examples).
// here...
.forEach(issueTemp -> {
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("mySecondURI" + issueTemp.getId())
.retrieve()
.bodyToMono(Issue.class)
.flatMap(issueTemp2-> {
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'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 -> {
return getIssue(issue.getId())
.flatMap(response -> {
return issue.setSummary(reponse.getSummary());
});
}).collectList();
Upvotes: 3