Search code examples
springspring-bootreactive-programmingspring-webfluxproject-reactor

How to collect paginated API responses using spring boot WebClient?


I have a paginated response from an URL, I want to keep on hitting the next page URL which I get from the previous response and keep on collecting items till I don't have a "nextPage" URL in my response. How to achieve this in a reactive way using spring boot WebClient from WebFlux with out blocking?

Request1: 

    GET /items
    response: 
    {
        items: [...]
        nextPage: "/items?page=2"
    }


    Request2: 

    GET /items?page=2
    response: 
    {
        items: [...]
        nextPage: "/items?page=3"
    }


    Request3: 

    GET /items?page=3
    response: 
    {
        items: [...]
        nextPage: null
    }

Here I have created mock urls https://karthikdivi.com/apps/paginatedReviews/withNextPageTokens/items https://karthikdivi.com/apps/paginatedReviews/withNextPageTokens/items?page=2 https://karthikdivi.com/apps/paginatedReviews/withNextPageTokens/items?page=3

How can I extract all Items from the above responses in a reactive way without blocking?


Solution

  • Using expand, this can be achieved. Based on the mock urls provided by you.

    public Mono<List<Item>> getItems() {
        String url = "https://karthikdivi.com/apps/paginatedReviews/withNextPageTokens/items";
    
        return fetchItems(url).expand(response -> {
            if (response.getNextPage() == null) {
                return Mono.empty();
            }
            return fetchItems(response.getNextPage());
        }).flatMap(response -> Flux.fromIterable(response.getItems())).collectList();
    }
    
    private Mono<Response> fetchItems(String url) {
    
             return client.get().uri(url).retrieve()
                        .bodyToMono(Response.class);
        }