If you need to do only simple, non-blocking checks i.e. checking some fields (or in general - not requiring playing another Mono/Flux), you can do it in doOnNext operator and easily extract to another method. Any exception thrown inside this block will be translated to Mono.error
final String parentId = specs.getParentId();
parentRepository.getById(parentId)
.switchIfEmpty(Mono.error(new ResponseStatusException(HttpStatus.BAD_REQUEST, "Parent does not exist")))
.doOnNext(parent -> {
if (parent.getSomeField() == null) { //this can be easily extracted for readability
throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "Some field must not be null");
}
})
.then(Mono.just(new Child(specs.getParentId(), specs.getName()))
.flatMap(childRepository::insert)
.switchIfEmpty(Mono.error(new ResponseStatusException(HttpStatus.BAD_REQUEST, "Failed to create child")));
If performing checks need to involve another Mono/Flux (for example calling another webservice), it will require using 'subscribing' operators such as flatMap or zip.
@Override
public Mono<Child> create(CreateChildRequest specs) {
final String parentId = specs.getParentId();
parentRepository.getById(parentId)
.switchIfEmpty(Mono.error(new ResponseStatusException(HttpStatus.BAD_REQUEST, "Parent does not exist")))
.flatMap(parent -> validate(parent))
.then(Mono.just(new Child(specs.getParentId(), specs.getName()))
.flatMap(childRepository::insert)
.switchIfEmpty(Mono.error(new ResponseStatusException(HttpStatus.BAD_REQUEST, "Failed to create child")));
}
}
Mono<Void> validate(Parent parent){
//some non blocking io logic ending with Mono.empty or Mono.error
}
Mono<Parent>contain null? but you should do yourparentRepository.getById(parentId)and then chain on it to do the checks and if good thenchildRepository.insert