Reputation:
I'm currently trying to understand Reactor and refactored a service method that returned an Optional<CompanyDetails>
to use Reactor's Mono<CompanyDetails>
instead:
public Mono<CompanyDetails> findOne(String id) {
CompanyDetails result = retrieveFromSomewhere(id);
return Mono.justOrEmpty(result);
}
From my understanding this should emit either empty()
or just(result)
.
I consume the service in a Spring web Controller like that:
@RequestMapping(value = "{id}", method = RequestMethod.GET)
public DeferredResult<CompanyDetails> getCompany(@PathVariable String id) {
final DeferredResult<CompanyDetails> result = new DeferredResult<>();
companyService.findOne(id)
.consume(result::setResult);
return result;
}
This works fine if a result was found, but if findOne
emits empty()
it runs into a timeout. I could call get()
explicitly and check for null
, but that feels totally wrong.
Also: Before refactoring, getCompany
threw a NotFoundException
if no result was found, is that possible at all, or am I on the wrong track entirely?
Upvotes: 4
Views: 1596
Reputation:
Found the answer myself: First it turned out that Reactor's Mono
has a toCompletableFuture
-method and Spring MVC can also use that instead of DeferredResult
. Failing the CompletableFuture
throws an Exception just as expected.
To fail, Mono
has to emit an error
instead of empty
:
public Mono<CompanyDetails> findOne(String id) {
CompanyDetails result = retrieveFromSomewhere(id);
return Mono
.justOrEmpty(result)
.otherwiseIfEmpty(Mono.error(...));
}
@RequestMapping(value = "{id}", method = RequestMethod.GET)
public CompletableFuture<CompanyDetails> getCompany(@PathVariable String id) {
return companyService.findOne(id)
.toCompletableFuture();
}
Much better now.
Upvotes: 3