Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

rxjava2 - if else on Maybe

Tags:

java

rx-java2

I am looking for what is the recommended practice in rxjava2 to handle a case where one flowable leads to conditional behaviors.

More concretely, I have a Maybe<String> for which I want to Update the String on the database if the String exists or, if it doesn't exists I want to create a new String and save it on the database.

I thought of the below but obviously it is not what I am looking for:

Maybe<String> source = Maybe.just(new String("foo")); //oversimplified source
source.switchIfEmpty(Maybe.just(new String("bar"))).subscribe(result -> 
System.out.println("save to database "+result));
source.subscribe(result -> System.out.println("update result "+result));

The above obviously produces

save to database foo
update result foo

I tried also the below which gives the expected result but still feel it's... weird.

Maybe<String> source = Maybe.just(new String("foo")); //oversimplified source
source.switchIfEmpty(Maybe.just(new String("bar")).doOnSuccess(result -> 
System.out.println("save to database "+result))).subscribe();
source.doOnSuccess(result -> System.out.println("update result "+result)).subscribe();

How can I have an action for when the result exists and when it doesn't exists? How is that use case supposed to be handled in rxjava2?

Update 01

I tried the below and it looks cleaner than what I came up with above. Note sure it is recommended rxjava2 practice however...

Maybe.just(new String("foo"))
     .map(value -> Optional.of(value))
     .defaultIfEmpty(Optional.empty())
     .subscribe(result -> {
         if(result.isPresent()) {
             System.out.println("update result "+result);
         }
         else {
             System.out.println("save to database "+"bar");
         }
     });
like image 564
simon Avatar asked Nov 03 '17 12:11

simon


People also ask

How many objects can maybe return?

Since it can only emit one value, it doesn't support backpressure handling as with a Flowable: Maybe. just(1) .

What is Maybe in rxjava?

The Maybe class represents a deferred computation and emission of a single value, no value at all or an exception. The Maybe class implements the MaybeSource base interface and the default consumer type it interacts with is the MaybeObserver via the subscribe(MaybeObserver) method.


2 Answers

You have the isEmpty() operator that will return you Boolean if the Maybe source is empty or not, and then you can flatMap it and write a if else statement depending on that Boolean

like image 142
Tooroop Avatar answered Sep 21 '22 22:09

Tooroop


This is a common pattern in our code as well, though in our case the choices are themselves async. You can't get quite the right semantic by simply composing flatMapX and switchIfEmpty (in either order), so I am curious why this isn't part of the API.

Here's what we're doing for now (this example for when the 2 options are both Completables, we have similar things for the other types as well):

public static <T> Completable flatMapCompletable(Maybe<T> target, 
                                                 @ClosureParams(FirstParam.FirstGenericType.class) 
                                                         Closure<? extends CompletableSource> completableSupplier, 
                                                 Supplier<CompletableSource> emptySupplier) {
    Maybe<T> result = target.cache();
    return result.isEmpty().flatMapCompletable(empty -> {
       if (empty) {
           return emptySupplier.get();
       } else {
           return result.flatMapCompletable(completableSupplier::call);
       }
    });
}

We're using Groovy, so we package these up as extension methods. I'm not thrilled with the need to use cache() so I'm wondering if there is a better alternative. From looking at the code, an operator which basically combines flatMapX and switch looks like it wouldn't be too hard (but I feel like I'm missing something).

like image 29
sfitts Avatar answered Sep 20 '22 22:09

sfitts