2

I am trying to implement the following simple imperative logic:

boolean saveImperative(final List list) {
    final String existingList = readByNameImperative(list.getName());
    if (Objects.isNull(existingList)) {
        templateSaveImperative(existingList);
        return true;
    } else {
        templateSaveImperative(existingList);
        return false;
    }
}

using Project Reactor in declarative way and this is what I was able to achieve:

@Test
public void testDeclarative() {
    final Mono<List> list = createList("foo");
    final Boolean result = save(list).block();
    System.out.println(result);
}

private Mono<Boolean> save(final Mono<List> listMono) {
    final Mono<List> existingListMono = listMono.cache()
            .flatMap(list -> readByName(list.getName()));
    // if
    final Mono<List> savedListMono = existingListMono
            .flatMap(existingList -> templateSave(Mono.just(existingList)));
    final Mono<Boolean> trueResult = savedListMono.map(x -> true);

    // else
    return trueResult.switchIfEmpty(templateSave(existingListMono).map(x -> false));
}

private Mono<List> templateSave(final Mono<List> listMono) {
    return listMono.map(list -> {
        System.out.println("templateSave has been called");
        return list;
    });
}

private Mono<List> readByName(final String listName) {
    if (listName != "list001") {
        return Mono.empty();
    }

    return createList(listName);
}

private Mono<List> createList(final String name) {
    final List list = List.builder().name(name).build();
    return Mono.just(list);
}

@Value
@Builder
private static class List {
    private final String name;
}

If I execute the test with list001, it will print:

templateSave has been called
true

as expected, but if I call it with foo, then I got

null

What I would be missing? I would expect an output like:

templateSave has been called
false

in that case.

hms
  • 35
  • 5

1 Answers1

0
final Mono<List> existingListMono = listMono.cache()
    .flatMap(list -> readByName(list.getName()));

...in your save method, will take your existing list and flat map it using readByName().

Your readByName() method is the following:

private Mono<List> readByName(final String listName) {
    if (listName != "list001") {
        return Mono.empty();
    }

    return createList(listName);
}

(I don't believe it's related to this problem, but don't use == or != for comparing strings.)

Since your listName is foo, not list001, it returns an empty Mono - thus existingListMono becomes an empty Mono, and by implication so do savedListMono and trueResult.

When you call your switchIfEmpty() statement however, you pass in templateSave(existingListMono) - and since existingListMono is an empty Mono as above, the save() method returns an empty Mono.

...and when you block on an empty Mono you'll get null - hence the result.

As such, you may wish to use listMono instead of existingListMono in your return statement on the save() method, which will give you the result you're after:

trueResult.switchIfEmpty(templateSave(listMono).map(x -> false))
Michael Berry
  • 70,193
  • 21
  • 157
  • 216