Reputation: 33
I'm currently making my first ever reactive project with Spring WebFlux. Unfortunately, I already got a task assigned that I cannot seem to find a solution for. I would like to receive a Mono and perform operations on it, depending on what other Monos complete. My idea goes like this:
private Mono<ResourceModel> setResourcesIfExisting(String resourceName) {
return resourceService.findByFilter(resourceName)
.flatMap(res -> service1.findByFilter(resourceName).map(res::setResource))
.flatMap(res -> service2.findByFilter(resourceName).map(res::setResource))
.flatMap(res -> service3.findByFilter(resourceName).map(res::setResource))
;
}
A Mono will be found by the resourceService, note that this is already the same type that I want to return. But now, I have some other services that deliver resources and in therory there should be exactly one fulfilling resource mono across all of those services.
From my tests, it always works if I use one of those flatMaps but as soon as I have two or more consecutively the list that gets collected on the higher level method results empty (I am using the above method for each element of a Flux<String>
).
Would someone be able to give me a pointed why this happens? As said above, I barely understand what I'm doing but tried out a lot with no success so far.
Upvotes: 0
Views: 2561
Reputation: 147
The reason for the mentioned output is due to this.
Mono<ResourceModel>
from resourceService.findByFilter(resourceName)
which is not empty..flatmap
by calling service1.findByFilter(resourceName)
it may return empty.flatmap
s are not called as no element will be returned as flatmap
is called upon each element.Alternatively you can use the following to achieve what you expected
private Mono<ResourceModel> setResourcesIfExisting(String resourceName) {
return resourceService.findByFilter(resourceName)
.flatMap(res -> service1.findByFilter(resourceName)
.switchIfEmpty(service2.findByFilter(resourceName))
.switchIfEmpty(service3.findByFilter(resourceName))
.doOnEach(stringSignal -> res.setResource(stringSignal.get()))
.thenReturn(res));
}
thenReturn
will return the ResourceModel
even if all the service1,2,3 return empty.
Upvotes: 1