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.
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))