Dans mon cas d'utilisation où j'ai un microservice Spring Webflux avec Reactor Netty, j'ai les dépendances suivantes:
org.springframework.boot.spring-boot-starter-webflux
(2.0.1.RELEASE)org.springframework.boot.spring-boot-starter-data-mongodb-reactive
(2.0.1.RELEASE)org.projectreactor.reactor-spring
(1.0.1.RELEASE)Pour un cas très spécifique, j'ai besoin de récupérer certaines informations de ma base de données Mongo, et de les traiter en paramètres de requête envoyés avec mon WebClient
réactif. Comme le WebClient
ni le UriComponentsBuilder
accepte un éditeur (Mono/Flux), j'ai utilisé un appel #block()
pour recevoir les résultats.
Depuis reactor-core
(Version 0.7.6.RELEASE) qui a été inclus dans la dernière spring-boot-dependencies
(Version 2.0.1.RELEASE) il n'est plus possible d'utiliser: block()/blockFirst()/blockLast() are blocking, which is not supported in thread xxx
, voir -> https://github.com/reactor/reactor-netty/issues/312
Mon extrait de code:
public Mono<FooBar> getFooBar(Foo foo) {
MultiValueMap<String, String> parameters = new LinkedMultiValueMap<>();
parameters.add("size", foo.getSize());
parameters.addAll("bars", barReactiveCrudRepository.findAllByIdentifierIn(foo.getBarIdentifiers()) // This obviously returns a Flux
.map(Bar::toString)
.collectList()
.block());
String url = UriComponentsBuilder.fromHttpUrl("https://base-url/")
.port(8081)
.path("/foo-bar")
.queryParams(parameters)
.build()
.toString();
return webClient.get()
.uri(url)
.retrieve()
.bodyToMono(FooBar.class);
}
Cela a fonctionné avec spring-boot
Version 2.0.0.RELEASE, mais depuis la mise à niveau vers la version 2.0.1.RELEASE et donc la mise à niveau de reactor-core
Vers la version 0.7.6.RELEASE, il n'est plus autorisé .
La seule vraie solution que je vois est d'inclure également un référentiel bloc (non réactif)/client mongo, mais je ne sais pas si cela est encouragé. Aucune suggestion?
WebClient
n'accepte pas un type Publisher
pour son URL de requête, mais rien ne vous empêche de faire ce qui suit:
public Mono<FooBar> getFooBar(Foo foo) {
Mono<List<String>> bars = barReactiveCrudRepository
.findAllByIdentifierIn(foo.getBarIdentifiers())
.map(Bar::toString)
.collectList();
Mono<FooBar> foobar = bars.flatMap(b -> {
MultiValueMap<String, String> parameters = new LinkedMultiValueMap<>();
parameters.add("size", foo.getSize());
parameters.addAll("bars", b);
String url = UriComponentsBuilder.fromHttpUrl("https://base-url/")
.port(8081)
.path("/foo-bar")
.queryParams(parameters)
.build()
.toString();
return webClient.get()
.uri(url)
.retrieve()
.bodyToMono(FooBar.class);
});
return foobar;
}
Si quoi que ce soit, cette nouvelle inspection du cœur du réacteur vous a évité de planter toute votre application avec cet appel de blocage au milieu d'un gestionnaire WebFlux.