0

I am wondering how to go about doing some validation checks before creating a new object?

@Override
public Mono<Child> create(CreateChildRequest specs) {

    final String parentId = specs.getParentId();
    // TODO: Check if parent exists
    // parentRepository.getById(parentId) -> returns Mono<Parent>

    final Child newChild = new Child(specs.getParentId(), specs.getName());
    return childRepository.insert(newChild)
            .switchIfEmpty(Mono.error(new ResponseStatusException(HttpStatus.BAD_REQUEST, "Failed to create child")));
}

How to add the validation check in a non blocking way?

2
  • depends can the Mono<Parent> contain null? but you should do your parentRepository.getById(parentId) and then chain on it to do the checks and if good then childRepository.insert Commented Jul 9, 2019 at 9:51
  • Yes im looking for way to chain this. Is flatmap the only way? What if i have many logical checks? It will look ugly if i keep nesting codes inside? Commented Jul 9, 2019 at 10:54

2 Answers 2

1

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
}
Sign up to request clarification or add additional context in comments.

1 Comment

this is so much harder than imperative and can really look messy if there are lots of validations and logics 😨
0

Maybe something like this, havn't run the code but you get the gist of it.

@Override
public Mono<Child> create(CreateChildRequest specs) {

    final String parentId = specs.getParentId();
    return parentRepository.getById(parentId)
        .doOnSuccess(parent -> {
            verify(parent).doOnSuccess(() -> {
                childRepository.insert(newChild).doOnError(throwable -> {
                    throw new ResponseStatusException(
                        HttpStatus.BAD_REQUEST,
                        "Failed to create child")
                }).doOnError(throwable -> {
                    // some error handling here if not passing validation.
                })
            })
        })
}

private Mono<Void> verify(Parent parent) {

    if(parent == null)
        return Mono.error(// some error here);
    else
        Mono.empty();
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.