Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

rxjava2 - how to zip Maybe that can be empty?

Tags:

rx-java2

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?

like image 377
simon Avatar asked Jun 08 '17 16:06

simon


1 Answers

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 "";
    }
} 
like image 106
simon Avatar answered Oct 12 '22 23:10

simon