Problem z zagnieżdżonymi strzałami do api - webClient, reactor

0

Kolejno:
-pobieram product po id (ProductService.getProductWithParts)
-w odpowiedzi mam listę z idkami parts
-strzeal w streamie po każdą część - Part
-mając Product i listę Part próbuję stworzyć ProductDto

https://github.com/baambaam/demo/commit/36918b6b5b2a0c90d722c870a332bd31063a104a

błąd jaki dostaję:
java.lang.IllegalStateException: block()/blockFirst()/blockLast() are blocking, which is not supported in thread

Czyli chodzi o metodę ProductService.convertToProductDto, gdzie próbuję Wyciągnąć obiekt z Mono:

map(Mono::block)

Nie mam już pomysłu jak to rozwiązać. To oczywiście tylko przykład, żeby odzwierciedlał jako tako problem. Może macie jakiś pomysł co tam nie tak? Generalnie wszystko dzieje się w ProductService. Całość się kompiluje, ale wchodząc na localhost:8080/product/1 wywala ww błąd

4

Jeśli chcesz mieć w pełni reaktywny kod to Twoja metoda convertToProductDto nie powinna być blokująca (obecnie jest). Mając na wejściu obiekt typu Product powinieneś zadeklarować reaktywny pipeline, który doprowadzi do stworzenia oczekiwanego rezultatu, zamiast blokować się w iteracji:

    private Mono<ProductDto> convertToProductDto(Product product) {
        return Mono.just(product) // zaczynamy mając obiekt type Product
            .flatMapIterable(Product::getParts) // zmieniamy Mono na Flux z id części
            .parallel() // zrównoleglamy calle do API (opcjonalne)
            .runOn(Schedulers.elastic()) // strzelamy do API w osobnym thread poolu
            .flatMap(partClient::getPart) // wykonaj call do API
            .map(Stream::of).reduce(Stream::concat) // redukujemy ParallelFlux do Mono<Stream<Part>>>
            .map(parts -> parts.collect(Collectors.toList())) // zamieniamy stream na listę
            .map(parts -> createDto(product, parts)); // mając listę Part możemy skonstruować wynikowe DTO
    }

    private ProductDto createDto(Product product, List<Part> parts) {
        ProductDto productDto = new ProductDto();
        productDto.setId(product.getId());
        productDto.setName(product.getName());
        productDto.setParts(parts);
        return productDto;
    }
3

@java_noob jak chcesz się bawić w reative to musisz na wszystko patrzeć na zasadzie pipeline przez który płyną dane. To trochę tak jakbyś pisał w standardowej Javie ale na wejściu dostawał jakiś Stream<T> na wyjściu produkował Stream<S> a w samej metodzie nie wolno ci użyć żadnej operacji terminalnej na wejściowym streamie, żadnego collect ani nic.

1 użytkowników online, w tym zalogowanych: 0, gości: 1