Warm tip: This article is reproduced from stackoverflow.com, please click
java spring spring-webflux spring-webclient

Spring WebClient Call Two Dependent API

发布于 2020-04-03 23:20:54

I have two endpoints, the first is to http://localhost:8899/api/composition/appraisal, which will returns all performance appraisal data

[
    {
        "appraisalId": "ac234fbf-740c-4390-89d4-0e9753ad4d70",
        "employeeId": "emp-4613",
        "grade": "VERY_GOOD",
        "score": 94,
        "status": "NEW"
    },
    {
        "appraisalId": "e9baf663-aa6e-4af8-ae16-ef50c886df28",
        "employeeId": "emp-4623",
        "grade": "VERY_GOOD",
        "score": 94,
        "status": "NEW"
    }
]

I also have another endpoint to get bonus data http://localhost:8888/api/composition/bonus/{appraisal_id} which return bonus data based on appraisal id

{
    "appraisalId": "ac234fbf-740c-4390-89d4-0e9753ad4d70",
    "bonusAmount": 4760.0,
    "bonusPaidDate": "2019-06-30",
    "employeeId": "emp-4623",
    "paidToBankAccount": "8240996587"
}

Giving the appraisal_id from first API as parameter, I must merge the result from both API calls into PerformanceAppraisalWithBonus.java class

public class PerformanceAppraisalWithBonus {
    private UUID appraisalId;
    private double bonusAmount;
    private LocalDate bonusPaidDate;
    private String employeeId;
    private String grade;
    private int score;
    private String status;

    getters / setters
}

How can I achieve this using Spring WebClient?

Questioner
Timothy
Viewed
25
Raúl Ortiz 2020-02-01 04:43

assuming that the second api http://localhost:8888/api/composition/bonus/{appraisal_id} replies 204 No content when it does not find or does not exist the id and in turn assuming that the expected response is a list of PerformanceAppraisalWithBonus (Flux) then it would look like this:

webClient

@Component
public class TestClient {


  public Flux<Appraisal> firstServiceList() {

    return WebClient.create()
            .get()
            .uri("http://demo4307830.mockable.io/first")
            .accept(MediaType.APPLICATION_JSON)
            .retrieve()
            .bodyToFlux(Appraisal.class);

  }

  public Mono<AppraisalBonus> firstServiceFindId(UUID uuid) {

    return WebClient.create()
            .get()
            .uri("http://demo4307830.mockable.io/"+ uuid)
            .accept(MediaType.APPLICATION_JSON)
            .retrieve()
            .bodyToMono(AppraisalBonus.class);

  }
}

Service

@Service
public class AppraisalServiceImpl {

  @Autowired
  private TestClient testClient;

  public Flux<AppraisalCombine> combineTwo() {
    return testClient.firstServiceList()
            .flatMap(appraisal -> testClient.firstServiceFindId(appraisal.getAppraisalId())
                    .flatMap(appraisalBonus -> Mono.just(AppraisalCombine.builder()
                            .appraisalId(appraisalBonus.getAppraisalId())
                            .bonusAmount(appraisalBonus.getBonusAmount())
                            .bonusPaidDate(appraisalBonus.getBonusPaidDate())
                            .employeeId(appraisalBonus.getEmployeeId())
                            .grade(appraisal.getGrade())
                            .score(appraisal.getScore())
                            .status(appraisal.getStatus())
                            .build())));

  }
}

Controller

@RestController
@RequestMapping("/appraisal")
public class AppraisalController {

  @Autowired
  AppraisalServiceImpl appraisalService;

  @GetMapping(value = "/get")
  public Flux<AppraisalCombine> uploadSimple() {
    return appraisalService.combineTwo();
  }
}

result

[
    {
        "appraisalId": "ac234fbf-740c-4390-89d4-0e9753ad4d70",
        "bonusAmount": 4760.0,
        "bonusPaidDate": "2019-06-30",
        "employeeId": "emp-4623",
        "grade": "VERY_GOOD",
        "score": 94,
        "status": "NEW"
    }
]