Zavael
Zavael

Reputation: 2468

Using Spring Reactor Mono with multiple switchIfEmpty

I had a simple java validation flow like this example:


if (!request.isValid()) {
    throw new ValidationException("Its not valid");
}

if (!request.isCorrect()) {
    throw new IncorrectException();
}

return Mono.just(
        someService.process(request)
);

I tried to chain method calls to get rid of ifs but this does not work:

return Mono.just(request)
        .filter(req -> !req.isValid())
        .switchIfEmpty(Mono.error(new ValidationException("Its not valid")))
        .filter(req -> !req.isCorrect())
        .switchIfEmpty(Mono.error(new IncorrectException()))
        .flatMap(req -> Mono.just(someService.process(req)));

The problem is, even if it fails on isValid() the code goes on and the second switch overwrites the first one.

How could I make the code working and retain the chaining?

Upvotes: 1

Views: 2433

Answers (2)

Mano Kovacs
Mano Kovacs

Reputation: 1514

It is not working because the filters should be the opposite. You specify what passes, not what filtered out:

    return Mono.just(request)
    // lets through valid request only:
    .filter(req -> req.isValid()) 
    // if it was invalid, its empty, thus switches to error:
    .switchIfEmpty(Mono.error(new ValidationException("Its not valid"))) 
    // filters out which is not correct:
    .filter(req -> req.isCorrect())
    // if not correct, its empty, switch to error:
    .switchIfEmpty(Mono.error(new IncorrectException())) 
    .flatMap(req -> Mono.just(someService.process(req)));

Upvotes: 2

Thiago Farconi
Thiago Farconi

Reputation: 46

Have you tried to use "Mono.defer()"?

Your code would be something like:

return Mono.just(request)
            .filter(req -> !req.isValid())
            .switchIfEmpty(Mono.defer(() -> Mono.error(new ValidationException("Its not valid"))))
            .filter(req -> !req.isCorrect())
            .switchIfEmpty(Mono.defer(() -> Mono.error(new IncorrectException())))
            .flatMap(req -> Mono.just(someService.process(req)));

I had the same issue, and it worked for me.

You can read more about Mono.defer() on this thread:

what does Mono.defer() do?

Upvotes: 3

Related Questions