Andrey Serebryanskiy
Andrey Serebryanskiy

Reputation: 178

How to save object to reactive repository inside flux

I have list of answers on questions. I want to save those answers and then (after mongo gives them an id) add them to their questions.

Now I'm doing it this way:

public Flux<Answer> createAnswers(List<Answer> answers) {
    return answerRepository.saveAll(answers)
            .map(answer -> {
                questionRepository.findById(answer.getQuestionId())
                        .subscribe(question -> {
                            question.getAnswers().removeIf(ans -> Objects.equals(ans.getId(), answer.getId()));
                            question.getAnswers().add(answer);
                            questionRepository.save(question).block();
                        });
                return answer;
            });
}

I also tried with ..saveAll(answers).doOnNext() and doOnEach() but this way questions are not saved.

It seems that map is used to transform data but not for doing operations on each element. Also I'm a bit confused with call to block().

Is there a better way to achieve my aim?

Upvotes: 3

Views: 5223

Answers (1)

Brian Clozel
Brian Clozel

Reputation: 59086

You should never call subscribe/block on a Flux or a Mono within a method that returns a reactive type itself.

Doing so will decouple the current pipeline with what you're trying to achieve. Best case scenario, this will break backpressure support. In many cases, this might also break in surprising ways; for example, if your method is dealing with HTTP request/response or a session of some sort, the response/session might get closed with your other subscriber is trying to do something on it still.

I believe something like this is more consistent (although I'm missing a lot of context here, so it might not be the best way to achieve this):

public Flux<Answer> createAnswers(List<Answer> answers) {
        return answerRepository.saveAll(answers)
                .flatMap(answer -> {
                    return questionRepository
                            .findById(answer.getQuestionId())
                            .flatMap(question -> {
                                question.getAnswers().removeIf(ans -> Objects.equals(ans.getId(), answer.getId()));
                                question.getAnswers().add(answer);
                                return questionRepository.save(question);
                            })
                            .thenReturn(answer);
                });
    }

Upvotes: 7

Related Questions