simon
simon

Reputation: 559

rxjava2 - how to zip Maybe that can be empty?

I am attempting to make 3 web services calls (e.g.: getPhoneNumber, getFirstName, getLastName) and collect the answers into a common object Person. Any of the web services calls can return a Maybe.empty().

When attempting to zip the response together, rxjava2 skips over the zip operation and terminate normally (without having aggregated my answer).

For a simplified example, see below:

@Test
public void maybeZipEmptyTest() throws Exception {
    Maybe<Integer> a = Maybe.just(1);
    Maybe<Integer> b = Maybe.just(2);
    Maybe<Integer> empty = Maybe.empty();

    TestObserver<String> observer = Maybe.zip(a,  b, empty, (x, y, e) -> {
        String output = "test: a "+x+" b "+y+" empty "+e;
        return output;
    })
    .doOnSuccess(output -> {
        System.out.println(output);
    })
    .test();

    observer.assertNoErrors();
}

How can we collect empty values within a zip operation instead of having the zip operation skipped/ignored? If this is the wrong pattern to solve this problem, how would you recommend solving this?

Upvotes: 8

Views: 6996

Answers (1)

simon
simon

Reputation: 559

For most use cases, leveraging the defaultIfEmpty method is the right way to go.

For representing something which is ultimately optional (doesn't even use default), I used Java 8 Optional type to represent.

For example

@Test
public void maybeZipEmptyTest() throws Exception {
    Maybe<Optional<Integer>> a = Maybe.just(Optional.of(1));
    Maybe<Optional<Integer>> b = Maybe.just(Optional.of(2));
    Maybe<Optional<Integer>> empty = Maybe.just(Optional.empty());

    TestObserver<String> observer = Maybe.zip(a,  b, empty, (x, y, e) -> {
        String output = "test: a "+toStringOrEmpty(x)+" b "+toStringOrEmpty(y)+" empty "+toStringOrEmpty(e);
        return output;
    })
    .doOnSuccess(output -> {
        System.out.println(output);
    })
    .test();

    observer.assertNoErrors();
}

private String toStringOrEmpty(Optional<Integer> value){
    if(value.isPresent()){
        return value.get().toString();
    }
    else { 
        return "";
    }
} 

Upvotes: 4

Related Questions