olsxn
olsxn

Reputation: 23

Webflux updating object and returning another

I want to create a new ProjectGroup object and before it happens I want to check if user with owner_id has role GROUP_OWNER and if he hasn't then I want to add it.

Everything works fine until I want to save user to database which doesn't work (saving ProjectGroup works just fine).

Does anyone know how to solve this?

    public Mono<ProjectGroup> create(ProjectGroup p) {
    return userRepository.findByUsername(p.getOwner_id()).flatMap(user -> {
        if (user != null) {
            if (!user.getRoles().contains(User.Role.GROUP_OWNER)) {
                List<User.Role> roles = user.getRoles();
                roles.add(User.Role.GROUP_OWNER);
                user.setRoles(roles);
                userRepository.save(user);
                return groupRepository.save(p);
            }
            return groupRepository.save(p);
        } else return null;
    });
}

Upvotes: 2

Views: 2488

Answers (2)

Toerktumlare
Toerktumlare

Reputation: 14783

when you are calling userRepository.save(user); you are breaking the chain because you are ignoring the return value, so that line will never get executed.

you should do what you want to do, then execute the next part. This can be done in several ways, this is one way.

return userRepository.findByUsername(p.getOwner_id()) // This should return empty if nothing is found
    .flatMap(user -> {
        if (!user.getRoles().contains(User.Role.GROUP_OWNER)) {
            final List<User.Role> roles = user.getRoles();
            roles.add(User.Role.GROUP_OWNER);
            user.setRoles(roles);
            return userRepository.save(user);
        }
        return user;
    }
}).then(groupRepository.save(p));

You should never return null, and avoid null checks in reactive programming. If you wish to return "nothing" from a function you should instead return a Mono#empty so that the next function in the chain can be triggered.

Upvotes: 1

Michael Berry
Michael Berry

Reputation: 72344

Remember the general rule when working with reactor - nothing happens until you subscribe. In Webflux land it's the framework doing the subscribing, but the concept still applies; you must actively return a publisher so the framework has a chance to subscribe to it, otherwise it will never be executed.

In this example, assuming your repositories are reactive, then userRepository.save() will return a Mono - and you're just ignoring that returned Mono, which means that (as per the above explanation) the save will never occur.

Instead, you want to return a Mono that will combine your two results - that is, first do userRepository.save(user) (and ignore the returned value), then do groupRepository.save(p). There's a dedicated method for this purpose, so you can simply do:

return userRepository.save(user).then(groupRepository.save(p));

On a more general note:

  • It's worth taking a look at the other methods available on Mono and Flux, as if you're working with reactor, you'll inevitably find yourself using them often.
  • null isn't allowed in a reactive stream - so your if (user != null) { check is redundant.

Upvotes: 0

Related Questions