Reputation: 35
I want to be able to wait for a List of Monos to get resolved and upon completion of the last element, proceed with another async call
public Mono<Artist> getArtistInfo(String id) {
//Call API1
Mono<MusicResponse> musisResponseMono = webClientBuilder
.build()
.get()
.uri(uri + "\\" + id)
.retrieve()
.bodyToMono(MusicResponse.class);
//1.async handler for the first call
return musisResponseMono.flatMap(musicRes ->{
Artist artist = new Artist();
List<Albums> albums = musicRes.getAlbums();
//make mutiple concurrent API calls to API2
albums.stream().forEach( album -> {
webClientBuilder
.build()
.get().uri("API 2 URL")
.retrieve()
.bodyToMono(Covers.class)
.subscribe(cover -> artist.getAlbums().add(cover.getImage()));
});
//call API3 - want to wait untill all API calls 2 are completed
return webClientBuilder
.build()
.get()
.uri("API3 URL")
.retrieve()
.bodyToMono(Profiles.class)
.map( profileRes ->
artist.setDescription(profileRes.getDescription())
);
}
}
The problem is that API call 3 may return before every element of the second call is returned . I guess what I'm looking for is something like asycn await in Javascipt in the context of Spring Webflux
Upvotes: 2
Views: 6819
Reputation: 14732
I think this should work.
We first fetch the artists and map the response. During the mapping we fetch each album cover and get a List<Mono<Cover>>
bock.
We then merge these in a Flux#merge
that will emit each Cover
when they are available. So we can then on each emit doOnNext
and attach these to the artist.
When that is done, we just then
and return the artist object.
After these chain of events we can doOnSuccess
our second fetch and attach more information to the Artist
object.
public Mono<Artist> getArtistInfo(String id) {
return webClient.get()
.uri("/artist")
.retrieve()
.bodyToMono(ArtistResponse.class)
.flatMap(artistResponse -> {
final Artist artist = new Artist();
return Flux.fromIterable(artistResponse.getAlbums())
.parallel(2)
.runOn(Schedulers.parallel())
.map(albums -> webClient.get()
.uri("artist/albums")
.retrieve()
.bodyToMono(Covers.class))
.doOnNext(coversMono -> coversMono
.doOnSuccess(covers -> artist.getAlbums().add(covers)))
.thenReturn(artist);
})
.doOnSuccess(artist -> webClient.get()
.uri("/artist/profile")
.retrieve()
.bodyToMono(Profiles.class)
.doOnSuccess(profiles -> artist.setDescription(profiles.getDescription())));
}
Havn't run the code so can't guarantee it but at least it will give you some insight maybe and a step on the way.
Upvotes: 3