2
votes

I'm new to Spring and even newer to WebClient. I want to filter the body of a Get response repeatedly with one second intervals for 2 minute duration using Springs' WebClient. I'm performing a get request which returns an empty JSON list of strings. At some moment of time the body is going to be populated and I want to return this list of strings. I want to filter the response in such way, that when it is empty it continues to perform the request until it is populated and return the desired result.

 private List<String> checkUser() {
        List<String> ibanList = new ArrayList<>();

        ExchangeFilterFunction filter = ExchangeFilterFunction.ofResponseProcessor(clientResponse -> {
            if (clientResponse.body())
                  //something here

        });

        Optional<Account[]> accountsOptional = webClient.get()
                .uri("example.com")
                .accept(MediaType.APPLICATION_JSON)
                .retrieve()
                .bodyToMono(Account[].class)
                .delaySubscription(Duration.ofSeconds(1))
                .retry()
                .filter(filter)
                .blockOptional(Duration.ofMinutes(2));

        if (accountsOptional.isPresent()) {

            for (Account account : accountsOptional.get()) {
                ibanList.add(account.getIban());
            }
            return ibanList;
        }
        return null;
    }

Does anybody have an idea how to do this? Any help would be appreciated.

2

2 Answers

0
votes

Instead of using bodyToMono you could use bodyToFlux instead and then use the interval method. You could separate out the request like this:

Flux<Account[]> request = webClient.get()
                .uri("example.com")
                .accept(MediaType.APPLICATION_JSON)
                .retrieve()
                .bodyToFlux(Account[].class);

and then call at interval using

Flux.interval(Duration.ofSeconds(1), Duration.ofMinutes(2))
  .map(i -> request)...

you can then chain your filter logic to this

0
votes

What did the trick for me was using flatMap to throw exception when the list is empty and then calling retryWhen, until the list is populated. (blockOptional removed, because not needed anymore)

Account[] accounts = webClient.get()
                    .uri("example.com")
                    .accept(MediaType.APPLICATION_JSON)
                    .retrieve()
                    .bodyToMono(Account[].class)
                    .delaySubscription(Duration.ofSeconds(1))
                    .flatMap(resp -> {
                        if (resp.length == 0) {
                            return Mono.error(Exception::new);
                        } else {
                            return Mono.just(resp);
                        }
                    })
                    .retryWhen(Retry.max(60))
                    .block();