Will
Will

Reputation: 1608

Spring 5 - Chain reactive webclient calls

I'm trying to learn how to use the reactive WebClient in Spring 5. Let's say I have 3 calls I need to make:

  1. Get an access token
  2. Get a list of accounts
  3. For each account, get a list of transactions.

Here, calls 2 and 3 each depend on the output of 1, whilst 3 also depends on the output of 2.

I know I can do something like:

accessTokenService
    .getAccessToken()
    .flatMapMany(accountsService::getAccounts)
    ...

But any subsequent calls to flatMap or doOnNext (or anything else) only have access to the accounts, not the access token.

My question I think boils down to:

If call 2 depends on the output of call 1, and call 3 depends on the output of calls 1 & 2, is there a standard way to accomplish this without having to use block()?

Edit for clarification: Call 3 requires the output of call 1 an input, and also the output of call 2 as input, e.g.:

accessTokenService
    .getAccessToken() // Call 1
    .flatMapMany((accessToken) -> accountsService.getAccounts(accessToken)) // Call 2
    .flatMapMany((accessToken, accounts) -> transactionService.getTransactions(accessToken, accounts)) // Call 3
    ...

Upvotes: 1

Views: 1418

Answers (2)

Nikolas
Nikolas

Reputation: 44486

Assuming the data classes Account, Token and Transaction, and the following service layer structure:

interface AccessTokenService {
    Mono<Token> getAccessToken();
}
interface AccountsService {
    Flux<Account> getAccounts(Token token);
}
interface TransactionService {
    Flux<Transaction> getTransactions(Token token, Flux<Account> account);
}

Then you can get all the transactions together for all accounts after receiving the token this way:

Flux<Transaction> transactions = accessTokenService
    .getAccessToken()
    .flatMapMany(token -> {
        final Flux<Account> accounts = accountsService.getAccounts(token);
        return transactionService.getTransactions(token, accounts);
    });

Note that all of the calls above are non-blocking.

What happens next with the transactions Flux is left to you:

  • You can block the first/last result.
  • You can return them all through the REST controller.
  • You can let them all consume it by a subscriber or R2DBC, you name it.

Upvotes: 1

Moncef AOUDIA
Moncef AOUDIA

Reputation: 687

You could achieve it using:

  1. Reactor Context, since version 3.1.3.
  2. Reactor Tuple.
  3. Create a wrapper object which contains data && access token.

Upvotes: 1

Related Questions