Search code examples
spring-bootreactive-programmingspring-webflux

How to return an object from Mono SpringWebFlux more effective?


I am using Spring Webflux, and I need to return the object of Author from Mono<Book>, But I don’t know how to do it more correctly.

The method that should return Author:

private Author getRegistredAuthor(Book bookInput) {
    String fullName = bookInput.getAuthor().getFullName();
    Optional<Author> optionalAuthor = repository.findByFullName(fullName).blockOptional();
    if(optionalAuthor.isPresent()){
        return optionalAuthor.get();
    }else {
        Author author = Author.builder().fullName(fullName).build();
        return repository.insert(author).block();
    }
}

The method that uses Author to create a new entity:


public Mono<BookDto> create(@RequestBody Book book) {
    book.setAuthor(getRegistredAuthor(book));
    return bookRepository.insert(book)
            .map(BookDto::of);
}

As I understand it, if I use block(), I will greatly reduce the effectiveness of reactive.

Will it be more effective if I use so ?

return repository.insert(author).blockOptional().get();

How would it be most efficient to return an object of Author?


Solution

  • As a result, I solved my problem using Mono.zip. Maybe my solution will help someone too:

        @PostMapping("/api/book")
        public Mono<BookDto> create(@RequestBody Book book) {
            return getObjectMono(book).flatMap(b -> bookRepository.insert(book))
                    .map(BookDto::of);
        }
    
    
        private Mono<Object> getObjectMono(Book book) {
            return Mono.zip(
                    getRegistredAuthor(book),
                    getRegistredGenre(book)
            ).map(objects -> {
                book.setAuthor(objects.getT1());
                book.setGenre(objects.getT2());
                return book;
            });
        }
    
        private Mono<Genre> getRegistredGenre(Book bookInput) {
            String genreTitle = bookInput.getGenre().getTitle();
            return genreRepository.findByTitle(genreTitle)
                    .switchIfEmpty(
                            genreRepository.insert(Genre.builder().title(genreTitle).build())
                    );
        }
    
        private Mono<Author> getRegistredAuthor(Book bookInput) {
            String fullName = bookInput.getAuthor().getFullName();
            return authorRepository.findByFullName(fullName)
                    .switchIfEmpty(
                            authorRepository.insert(Author.builder().fullName(fullName).build())
                    );
        }