Here's my code:
public Mono<Foo> doSomething(String fooId, String barId) {
Mono<Foo> firstResult = firstServiceCall(fooId, barId);
Mono<List<Baz>> secondResult = secondServiceCall(fooId);
return firstResult.flatMap(secondResult::thenReturn);
}
private Mono<Foo> firstServiceCall(String fooId, String barId) {
return fooRepo
.findByFooIdAndBarId(fooId, barId)
.switchIfEmpty(Mono.error(new ResponseStatusException(NOT_FOUND)))
.filter(Foo::isSomething)
.switchIfEmpty(Mono.error(new ResponseStatusException(UNPROCESSABLE_ENTITY)))
.doOnNext(foo -> foo.setSomething(false))
.flatMap(fooRepo::save);
}
private Mono<List<Baz>> secondServiceCall(String fooId) {
var filter = new BazSearchFilter();
filter.setFooId(fooId);
return bazRepo
.findAllByFilter(filter)
.doOnNext(baz -> baz.setStatus(BazStatus.SOMETHING))
.collectList()
.flatMapMany(bazRepo::saveAll)
.collectList();
}
For some reason, the doSomethingMethod always calls the secondServiceCall method despite an error signal being propagated from the firstServiceCall method (the NOT_FOUND or UNPROCESSABLE_ENTITY scenarios).
I would expect the secondServiceCall not to go off since I'm using flatMap, but maybe I'm missing something.
Does anyone know how to fix this?
You should just rewrite doSomething(...) method as follows:
public Mono<Foo> doSomething(String fooId, String barId) {
Mono<Foo> firstResult = firstServiceCall(fooId, barId);
return firstResult.doOnNext(foo -> secondServiceCall(fooId));
}
or as follows:
public Mono<Foo> doSomething(String fooId, String barId) {
Mono<Foo> firstResult = firstServiceCall(fooId, barId);
Mono<List<Baz>> secondResult = Mono.defer(() -> secondServiceCall(fooId));
return firstResult.flatMap(secondResult::thenReturn);
}
It is very interesting that this method also works as expected:
public Mono<Foo> doSomething(String fooId, String barId) {
Mono<Foo> firstResult = firstServiceCall(fooId, barId);
return firstResult.flatMap(foo -> secondServiceCall(fooId).thenReturn(foo));
}
definitely a lambda does the trick