0

I have a reactive code below which does the following.

  1. query items table by ID - (itemRepository.findByd(itemId))
  2. Create a map from the result from Step1
  3. Invoke retrieveItemsQty from DB

Here, it works fine when the Step1 returns one or more result and retrieveItemsQty method fails when the result is empty. My requirement is to return back when the first step result(itemRepository.findByd) is empty. Not sure how to do this?

private Mono<Long> updateItemsQty(final Long itemId) {
        return itemRepository.findByd(itemId).collectList()
                .zipWhen((items) -> Mono.just(items.stream()
                        .collect(Collectors.toMap(ItemQty::getId, ItemQty::getQty))))
                .map((tuple) -> tuple.getT2())
                .zipWhen((items) -> qtyRepository
                        .retrieveItemsQty(items.keySet()).collectList())
                .zipWhen((tuple) -> reduceItemQty(tuple.getT2(), tuple.getT1(), itemId))
                .flatMap((response) -> {
                    return Mono.just(itemId);
                });
    }

I tried switchIfEmpty and defaultIfEmpty like the below.

return itemRepository.findByd(itemId).collectList()
                    .switchIfEmpty(). /// Looks like the return statement is not allowed here.
                    .zipWhen((items) -> Mono.just(items.stream()
                            .collect(Collectors.toMap(ItemQty::getId, ItemQty::getQty))))
user1578872
  • 7,808
  • 29
  • 108
  • 206
  • Not sure what you mean by “return back when result is empty” but in general you can use ‘switchIfEmpty’ operator – Alex Mar 14 '22 at 06:18
  • @Alex I meant when itemRepository.findByd(itemId).collectList() is emptyList. Not sure if switchIfEmpty can be used next to this line for emptyList. – user1578872 Mar 14 '22 at 14:30
  • Unable to return next to the first statement. .switchIfEmpty(Mono.defer(() -> { return Mono.just(itemId); })) – user1578872 Mar 14 '22 at 14:34
  • ```.switchIfEmpty()``` will only work if your```Mono``` returned empty, if you want to check if the list is empty, you should use ```.filter(list -> list.isEmpty())``` – fmbordignon Mar 14 '22 at 16:56
  • Even I have this filter, How can I return it without executing the following zipWhen statements. – user1578872 Mar 14 '22 at 17:43

1 Answers1

1

In case you want to keep the current flow, the easiest way would be to use filter

return itemRepository.findByd(itemId)
   .collectList()
   .filter(items -> !items.isEmpty())
   ...

but I would suggest to simplify the flow to make it more readable and don't overuse reactive operators where you don't really need them. For example, something like

return itemRepository.findByd(itemId)
    .collectList()
    .flatMap(items -> {
        if (items.isEmpty()) {
            return Mono.empty();
        }

        Map<Long, Integer> itemMap = items.stream()
                .collect(Collectors.toMap(ItemQty::getId, ItemQty::getQty));

        return retrieveItemsQty(itemMap.keySet())
                .collectList()
                .flatMap(availableQty -> reduceItemQty(availableQty, itemMap, itemId));
    })
    .then(Mono.just(itemId));

you could simplify even futher and move inner body into a separate method

Alex
  • 4,987
  • 1
  • 8
  • 26