WebFlux - как проверить моно > пусто для возврата 404 - PullRequest
0 голосов
/ 07 мая 2020

Мой код:

public Mono<ResponseEntity<Flux<TreeItem>>> allGroups(
      @PathVariable(value = "email") String email, ServerWebExchange exchange) {

    return Mono.just(
            userGroupService
                .findGroupByEmail(email) //Flux<GroupById>
                .flatMap(getGroups(email)) //Flux<TreeItem>
                .map(TreeItem::getId) //Flux<UUID>
                .collectList() //Mono<List<UUID>>
                .flatMap(getFilteredGroupIdsForUserPrivilege())
                .flatMapMany(Flux::fromIterable) //Flux<UUID>
                .flatMap(getUserTreeGroups(email)))
        .map(ResponseEntity::ok)
        .defaultIfEmpty(ResponseEntity.notFound().build()); --> is not executed at all when no data are returned

Когда я передаю несуществующий адрес электронной почты, мой код возвращает ответ 200 с пустым массивом: []

В этом случае я хотел бы вернуть 404 error - почему не выполняется последняя строка?

.defaultIfEmpty(ResponseEntity.notFound().build());

Метод getUserTreeGroups:

private Function<UUID, Publisher<? extends TreeItem>> getUserTreeGroups(String email) {
    return filteredGroupId -> userGroupService
        .findUserTreeGroup(filteredGroupId, email);
  }

И метод findUserTreeGroup:

public Mono<GroupTreeItem> findUserTreeGroup(UUID groupId, String email) {
    return groupByIdRepo.findById(groupId)
            .flatMap(group -> findChildData(email, group));
  }

Я хочу вернуться к внешний интерфейс список TreeItem. И если честно - до сих пор не понимаю, когда использовать Mono<ResponseEntity<Flux<TreeItem>>>, а может, Mono<ResponseEntity<List<TreeItem>>>? В чем разница?

ОБНОВЛЕНИЕ После применения решения Томаса Андольфа:

public Mono<ResponseEntity<Flux<TreeItem>>> userAllTreeGroups(
    @PathVariable(value = "email") String email, ServerWebExchange exchange) {
    return userGroupService
              .findUserGroupByEmail(email) //Flux<GroupById>
              .flatMap(groupById -> userGroupService.findUserTreeGroup(groupById.getId(), email)) //Flux<TreeItem>
              .map(TreeItem::getId) //Flux<UUID>
              .collectList() //Mono<List<UUID>>
              .flatMap(groupIds ->
                  rolePrivilegesService.filterGroupIdsForUserPrivilege(groupIds, GROUP_USER_READ_PRIVILEGE))
              .flatMapMany(Flux::fromIterable) //Flux<UUID>
              .flatMap(filteredGroupId -> userGroupService.findUserTreeGroup(filteredGroupId, email)) //Flux<GroupItem>
              .collectList() //Mono<List<TreeItem>>
              .map(ResponseEntity::ok) //Mono<ResponseEntity<List<TreeItem>>>
              .defaultIfEmpty(ResponseEntity.notFound().build());

Но все равно мне нужно вернуть Mono >>.

Какой метод должен мне вернуть, по вашему мнению? Mono >> как в вашем решении ???

1 Ответ

1 голос
/ 07 мая 2020

Во втором комментарии я спросил

Почему вы помещаете все в Mono.just()?

И вы не ответили, хорошо, если вы действительно читали это решило бы это, потому что это, вероятно, вызывает вашу проблему.

final List<String> strings = Collections.emptyList();

// You are wrapping a flux in a mono for some strange reason?
final Mono<Flux<String>> wrappedFlux = Mono.just(Flux.fromIterable(strings)
        .flatMap(s -> Mono.just("This never gets run"))
).defaultIfEmpty(Flux.just("This never gets run either, because there is a flux in the mono"));

переписано

// Can't test it but something in the lines of the following
return userGroupService
            .findGroupByEmail(email) //Flux<GroupById>
            .flatMap(getGroups(email)) //Flux<TreeItem>
            .map(TreeItem::getId) //Flux<UUID>
            .collectList() //Mono<List<UUID>>
            .flatMap(getFilteredGroupIdsForUserPrivilege())
            .flatMapMany(Flux::fromIterable) //Flux<UUID>
            .flatMap(getUserTreeGroups(email)))
            .collectList()
            .map(ResponseEntity::ok)
            .defaultIfEmpty(ResponseEntity.notFound().build());

A Mono<T> - это одно из будущих вычислений. Когда кто-то подписывается на него, он будет пытаться решить, что в нем находится, а когда его внутренний статус превратится в COMPLETED, он выстреливает из него.

A Flux<T> - это то же самое, но для многих объектов. Вы можете подумать, столько же Mono<T> s и таких же, как и раньше, когда кто-то подписывается на него, он попытается решить проблемы внутри каждого элемента в Flux<T> и выбросит их, как только статус достигнет COMPLETED для каждого.

Ничего не произойдет, пока вы не подпишетесь на Mono<T> or a Flux`.

Если у вас есть Mono<Flux<T>> при подписке, это попытается разрешить все, что в нем, и то, что в нем, - это Flux<T>, так что он будет удален напрямую.

С другой стороны, Flux<T>, никто не подписался, поэтому ничего в этом разрешено. Он практически мертв, пуст, не используется.

Вы меня спрашиваете:

Так что, по вашему мнению, бессмысленно / бессмысленно иметь Flux внутри Mono

Я только что написал выше, основы работы реактивного программирования. Вы отправляете Flux<T> из Mono<T>, на которое никто не подписывался.

и ничего не происходит, если вы не подпишетесь.

Полагаю, вы прочитали документацию для реактора с самого начала очень полезно понять основные c концепции реактивного программирования

Я не знаю, чего вы пытаетесь достичь, так как у меня нет ваша полная кодовая база, я понятия не имею, что вы возвращаете.

...