Martin
Martin

Reputation: 1267

How to pass Mono<> result from previous step to the next doOnSuccess() method

Let's say that I have a method addVoteToSong like:

public Mono<Map<Song, VoteKind>> addVoteToSong(Principal principal, String songId, VoteKind voteKind) {
        return
            userRepository.findUserByUsername(principal.getName())
            .doOnSuccess(song -> songRepository.findSongById(songId))
            .doOnSuccess(vote -> voteRepository.add(Vote.builder().song()))
            .//(the rest of the code) 
}

I want to pass a result from the line:

userRepository.findUserByUsername(principal.getName())

and

.doOnSuccess(song -> songRepository.findSongById(songId))

to the built object in the line:

.doOnSuccess(vote -> voteRepository.add(Vote.builder().song(here result from findSongById).user(here result from findUserByUsername))

Here comes the question, is it possible to reuse previous API call result in the next doOnSuccess method or I should split find API calls at the same time, giving up on Reactor's cascading operations? On the internet, I have found examples with single save method without basing on the indirect result of the reactive stream and that's why question occurred. I will be grateful for suggestions on how to reach a goal.

Upvotes: 0

Views: 3299

Answers (1)

Stepan Tsybulski
Stepan Tsybulski

Reputation: 1201

Martin,

First of all, be aware that .doOnXXX are just callbacks that will be executed on some archived conditions. You should avoid putting a business logic inside of them.

Coming back to the question, the first idea that comes to my mind is to benefit from zip operator. So you have to put 2 publishers .findUserByUsername and .findSongById and combine the result using BiFunction. So you can try the following:

public Mono<Map<Song, VoteKind>> addVoteToSong(Principal principal, String songId, VoteKind voteKind) {
    return Mono
            .zip(
                    userRepository.findUserByUsername(principal.getName()),
                    songRepository.findSongById(songId),
                    (user, song) -> voteRepository.add(Vote.builder().song(song).user(user).build())
            )
            .flatMap(Function.identity())
            // your code is here
}

Upvotes: 6

Related Questions