So my goal is to use WebClient to make multiple concurrent requests, wait until they’re all completed, then combine the results. Here is what I have so far:
Flux<ServerResponse> feedResponses = request
.bodyToMono(AddFeedRequestDto.class)
.map(AddFeedRequestDto::getFeeds) // Returns a list of RSS feed URLs
.map(this::getServerResponsesFromUrls) // Returns a list of Mono<Feed>
.map(Flux::merge) // Wait til all requests are completed
// Not sure where to go from here
/** Related methods: **/
private List<Mono<Feed>> getServerResponsesFromUrls(List<String> feedUrls) {
List<Mono<Feed>> feedResponses = new ArrayList<>();
feedUrls.forEach(feedUrl -> feedResponses.add(getFeedResponse(feedUrl)));
return feedResponses;
}
public Mono<Feed> getFeedResponse(final String url) {
return webClient
.get()
.uri(url)
.retrieve()
.bodyToMono(String.class) // Ideally, we should be able to use bodyToMono(FeedDto.class)
.map(this::convertResponseToFeedDto)
.map(feedMapper::convertFeedDtoToFeed);
}
/** Feed.java **/
@Getter
@Setter
public class Feed {
List<Item> items;
}
Basically my goal is to combine all the items from each of the feeds to create one unified feed. However, I am not quite sure what to do after the call to Flux::merge. Any suggestions would be appreciated.
Advertisement
Answer
Use .flatMap
instead of .map
/ Flux.merge
, like this:
Mono<Feed> unifiedFeedMono = request
.bodyToMono(AddFeedRequestDto.class) // Mono<AddFeedRequestDto>
.map(AddFeedRequestDto::getFeeds) // Mono<List<String>> feedUrls
.flatMapMany(Flux::fromIterable) // Flux<String> feedUrls
.flatMap(this::getFeedResponse) // Flux<Feed>
.map(Feed::getItems) // Flux<List<Item>>
.flatMap(Flux::fromIterable) // Flux<Item>
.collectList() // Mono<List<Item>>
.map(Feed::new); // Mono<Feed>
Note that .flatMap
is an asynchronous operation and will execute requests in parallel. There is an overloaded version that takes a concurrency
argument if you want to limit concurrency.
Ordering is not guaranteed with .flatMap
, and the resulting items might be interleaved. If you want more ordering guarantees, substitute .concatMap
or .flatMapSequential
.