How to perform an action only if the Mono is empty and throw an error it not empty

cgaskill :

I'm trying to convert a project to use Spring WebFlux and am running into a problem getting some basic business logic working. I have a repository layer that is responsible for retrieving / persisting records and a service layer that is responsible for the business rules of the application. What I want to do (in the service) layer is check if a user already exists for the given username. If so, I want to respond with an error. If not, I want to allow the insert to happen.

I call a method on the repository layer that will find a user by username and if not found it will return an empty Mono. This is working as expected; however, I have tried various combinations of flatMap and (defaultIfEmpty and swithIfEmpty) but am unable to get it to compile / build.

    public Mono<User> insertUser(User user) {
        return userRepository.findByUsername(user.username())
            .flatMap(__ -> Mono.error(new DuplicateResourceException("User already exists with username [" + user.username() + "]")))
            .switchIfEmpty(userRepository.insertUser(user));
    }

The error that I'm getting is that Mono<Object> cannot be converted to Mono<User>, so the swithIfEmpty doesn't seem to reflect the appropriate type and casting doesn't seem to work either.

cgaskill :

After additional testing, and taking into consideration the responses from my fellow developers, I have landed on the following solution:

    public Mono<User> insertUser(User user) {
        return userRepository.findByUsername(user.username())
            .flatMap(__ -> Mono.error(new DuplicateResourceException("User already exists with username [" + user.username() + "]")))
            .switchIfEmpty(Mono.defer(() -> userRepository.insertUser(user)))
            .cast(User.class);
    }

As Thomas stated, the compiler was getting confused. My assumption is because the flatMap was returning a Mono with an error and the switchIfEmpty was returning a Mono with a User so it reverts to a Mono with an Object (hence the additional .cast operator to get it to compile).

The other addition was to add the Mono.defer in the switchMap. Otherwise, the switchIfEmpty was always firing.

I'm still open to other suggestions / alternatives (since this seems like it would be a fairly common need / pattern).

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326903&siteId=1