In my use case where I have a Spring Webflux microservice with Reactor Netty, I have the following dependencies:
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)
For a very specific case I need to retrieve some information from my Mongo database, and process this into query parameters send with my reactive WebClient. As the WebClient nor the UriComponentsBuilder accepts a Publisher (Mono / Flux) I used a #block() call to receive the results.
Since reactor-core (version 0.7.6.RELEASE) which has been included in the latest spring-boot-dependencies (version 2.0.1.RELEASE) it is not possible anymore to use: block()/blockFirst()/blockLast() are blocking, which is not supported in thread xxx, see -> https://github.com/reactor/reactor-netty/issues/312
My code snippet:
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);
}
This worked with spring-boot version 2.0.0.RELEASE, but since the upgrade to version 2.0.1.RELEASE and hence the upgrade from reactor-core to version 0.7.6.RELEASE it is not allowed anymore.
The only real solution I see is to include a block (non-reactive) repository / mongo client as well, but I'm not sure if that is encouraged. Any suggestions?
The WebClient does not accept a Publisher type for its request URL, but nothing prevents you from doing the following:
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;
}
If anything, this new reactor-core inspection saved you from crashing your whole application with this blocking call in the middle of a WebFlux handler.
来源:https://stackoverflow.com/questions/49746372/how-to-execute-blocking-calls-within-a-spring-webflux-reactor-netty-web-applic