1

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?

Dinesh Narayan
  • 105
  • 2
  • 9

1 Answers1

3

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 -> {
    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();
Toerktumlare
  • 12,548
  • 3
  • 35
  • 54
  • Thanks. Actually that was my bad. I missed the return statement while posting the question. Can you please suggest now. Also will keep in mind about the readability next time. – Dinesh Narayan May 04 '20 at 10:01
  • You are missing more return statements still, i posted three places, you have fixed one. – Toerktumlare May 04 '20 at 10:06
  • Correct me if I am wrong, but I do have return statements for the rest of the two cases. Mono.just(issue) and Mono.just(responseFinal). Could you please hel me further. May be I am unable to see the point. – Dinesh Narayan May 04 '20 at 10:23
  • @DineshNarayan `.flatMap(resp->{ return resp...` and `doSomethingWithThisVariable = webClient.get()...log().block();` –  May 04 '20 at 12:41
  • Thanks for the reply. block() makes my api blocking one. I am trying to create a non blocking api – Dinesh Narayan May 04 '20 at 13:20
  • i have updated my answer, and this can be seriously refactored hard to look alot cleaner look into using functionality like `Mono#then()` and `Mono#thenReturn()` also generify your WebClient calls into functions, and the handing of the responses into functions. And also stick your response in a flux instead of iterating through a list. – Toerktumlare May 04 '20 at 13:34
  • The way you have written this will never become non-blocking, you are iterating through a list and need to block until all answers are back until you can continue. You need take the `getissues`and stick them into a flux and do requests and `collectList` – Toerktumlare May 04 '20 at 13:42
  • I have updated my question. Can you please have a look. Thanks. – Dinesh Narayan May 04 '20 at 15:28
  • Can you please stop updating your question. I dont want to sit here and update my answer constantly. I concider this matter solved and if you have more issues you should ask a new question – Toerktumlare May 04 '20 at 17:19
  • 1
    @DineshNarayan The way you are doing stuff needs a block, if you create a mcve as stated above in question comments section then maybe we can make it non blocking. Anyways, this site is not for refactoring your code but to help with the already messed up code. I think thomas has given a nice answer and it should be marked as accepted. –  May 04 '20 at 18:03