web-dev-qa-db-ja.com

Spring Webflux:Monoから値を抽出する

私は春のwebfluxに不慣れで、2つのモノの値に対していくつかの演算を実行しようとしています。 webClient経由でアカウントサービスを呼び出してアカウント情報を取得する製品サービスがあります。アカウントの現在の残高が製品の価格以上かどうかを確認したい。

Mono<Account> account = webClientBuilder.build().get().uri("http://account-service/user/accounts/{userId}/",userId)
.retrieve().bodyToMono(Account.class);


//productId is a path variable on method
Mono<Product> product =this.productService.findById(productId);

ストリームをブロックしようとするとエラーが発生する

block()/ blockFirst()/ blockLast()はブロッキングですが、スレッドreactor-http-nio-2ではサポートされていません

//Causes Error
Double accountBalance = account.map(a->a.getBalance()).block():

Double productPrice = product.map(p->p.getPrice()).block();

///Find difference, send response accordingly....

これは正しいアプローチですか?これを達成する別のより良い方法がありますか?私はまた、以下に沿って何かを考えていました:

Mono<Double> accountBalance = account.map(a->a.getBalance()):

Mono<Double> productPrice = product.map(p->p.getPrice());

Mono<Double> res = accountBalance.zipWith(productPrice,(b,p)-> b-p);

//Something after this.....

2
X2015jpp

メインのリアクタスレッドではブロックメソッドを使用できません。これは禁じられています。 blockは、他のスレッドでモノを公開するときに機能する場合がありますが、そうではありません。

基本的に、2つのモノを圧縮するというアプローチは正しいです。ヘルパーメソッドを作成して、それらを計算することができます。あなたの場合、それは次のようになります:

public boolean isAccountBalanceGreater(Account acc, Product prd) {
   return acc.getBalance() >= prd.getPrice();
}

そして、Monoストリームでメソッド参照を渡し、読みやすくすることができます。

Mono<Boolean> result = account.zipWith(productPrice, this::isAccountBalanceGreater)

問題は、後でその情報をどのように処理するかです。コントローラに戻りたい場合は、trueまたはfalseでかまいません。それ以外の場合は、他のマッピング、圧縮などが必要になる場合があります。

更新

return account.zipWith(productPrice, this::createResponse);

...

ResponseEntity createResponse(Account acc, Product prd) {
   int responseCode = isAccountBalanceGreater(acc, prd) ? 200 : 500;
   return ResponseEntity.status(responseCode).body(prd);
}
1
Bartosz Kiebdaj