Rxjava: 2.x Emit null reference item using Observable.just

Created on 5 Sep 2016  ·  17Comments  ·  Source: ReactiveX/RxJava

Hi.

In RxJava 1.x I use Observable.just(null) when I need to create an Observable which emits a null reference. I use this approach in some unit tests as such as when the parameterized Type is Void (Observable<Void>).

But now there is a precondition when calling Observable#just which forces to the supplied item to not be a null reference.

So, how can I create an Observable which emits a null reference?

Thanks.

Question

Most helpful comment

You can't. The Reactive-Streams specification forbids nulls thus we don't allow that either. If you don't have any value, use Completable.

All 17 comments

You can't. The Reactive-Streams specification forbids nulls thus we don't allow that either. If you don't have any value, use Completable.

Just like this?

Completable.complete().toObservable()

Yes.

Thanks :)

Btw, I think this is going to break a lot of client code. Not allowing to play with null values is a huge change.

With 1.x this test will pass:

        rx.observers.TestSubscriber<String> testSubscriber = new rx.observers.TestSubscriber<>();
        rx.Observable.just("")
            .map(new Func1<String, String>() {
                @Override public String call(String s) {
                    return null;
                }
            })
            .subscribe(testSubscriber);
        testSubscriber.awaitTerminalEvent();
        testSubscriber.assertNoErrors();
        testSubscriber.assertValueCount(1);

But with 2.x this test won't pass:

        TestObserver<String> testObserver = new TestObserver<>();
        Observable.just("")
            .map(new Function<String, String>() {
                @Override public String apply(String s) throws Exception {
                    return null;
                }
            })
            .subscribe(testObserver);
        testObserver.awaitTerminalEvent();
        testObserver.assertNoErrors();
        testObserver.assertValueCount(1);

Because you are collecting now feedback about 2.x version, I just wanted to point out that this change -in my opinion- can potentially break a lot of client code.

Yes, 2.x is a breaking change in this regard. Just return an element of some other type. I tend to use Integer and 1.

It is behind a major version bump along with many other changes that have
the opportunity to break client code without proper care. Besides, RxJava
doesn't have a choice in the matter because of the reactive streams spec.

On Mon, Sep 5, 2016 at 11:11 AM Víctor Albertos [email protected]
wrote:

Thanks :)

Btw, I think this is going to break a lot of client code. Not allowing to
play with null values is a huge change.

With 1.x this test will pass:

    rx.observers.TestSubscriber<String> testSubscriber = new rx.observers.TestSubscriber<>();
    rx.Observable.just("")
        .map(new Func1<String, String>() {
            @Override public String call(String s) {
                return null;
            }
        })
        .subscribe(testSubscriber);
    testSubscriber.awaitTerminalEvent();
    testSubscriber.assertNoErrors();
    testSubscriber.assertValueCount(1);

But with 2.x this test won't pass:

    TestObserver<String> testObserver = new TestObserver<>();
    Observable.just("")
        .map(new Function<String, String>() {
            @Override public String apply(String s) throws Exception {
                return null;
            }
        })
        .subscribe(testObserver);
    testObserver.awaitTerminalEvent();
    testObserver.assertNoErrors();
    testObserver.assertValueCount(1);

Because you are collecting now feedback about 2.x version, I just wanted
to point out that this change -in my opinion- can potentially break a lot
of client code.


You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
https://github.com/ReactiveX/RxJava/issues/4475#issuecomment-244768638,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AAEEEWnQAdp39-onIMhomdiqD9vpSTvXks5qnDEzgaJpZM4J1Ela
.

Ok then 👍

Are Subjects with Void type still allowed?

There's no restriction on type parameters.

On Mon, Sep 5, 2016, 8:12 PM pakoito [email protected] wrote:

Are Subjects with Void type still allowed?


You are receiving this because you commented.

Reply to this email directly, view it on GitHub
https://github.com/ReactiveX/RxJava/issues/4475#issuecomment-244823902,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AAEEEbKOVhgv7f7EYHNb5gCBk7oodkwHks5qnLAHgaJpZM4J1Ela
.

Note that, although Void type parameters are allowed, having a Subject<Void> would be useless as you could not call onNext on it. null is the only inhabitant of the Void type and null is not allowed anywhere - even in subjects.

That's what I thought. I'll have to create a new Hood-like type with a single constructor.

*Void

@JakeWharton Jake god, I encounter a similar issue.
I hava Rxjava and Retrofit to handle the response from a http server.

sometimes, data response is in this format:

{
  code: 'OK',
  data: {.....}
}

and sometimes, the data property doesn't exist.

{
  code: 'OK'
}

I try to return null, when data property doesn't exist, but Rxjava throw Exception.
In the customize Observer, I handle all success scenario in onNext(), so I need to make data == null also go to this logic.
but when data == null, I cannot return a T by return new T().
is there any method to help me out?

public static <T> Function<BaseResponse<T>, T> applyUnwrapResponse () {
        return new Function<BaseResponse<T>, T>() {
            @Override
            public T apply(@NonNull BaseResponse<T> baseResponse) throws Exception {
                if (baseResponse.getCode().equals(Constants.SUCCESS_CODE)) {
                    // http returned from server
                    T data = baseResponse.getData();
                    if (data == null) {
                        return null;  // throw exception: The mapper function returned a null value
                        return return new T(); // syntax error
                        // how ?
                    }
                    return data;
                } else if (baseResponse.getCode().equals(Constants.USER_NOT_LOGGED_IN)) {
                    // auth token error
                    throw new UserNotLoginException(baseResponse.getMsg());
                }
                // unknown error
                throw new UnknownServerException(baseResponse.getMsg());
            }
        };
    }

@JakeWharton I open a issue in stackoverflow

@njleonzhang leon, any progress?
i throw out a special exception, and catch exception in logic code.

@zhangchaoxu Yeah, It can work in this way. But this will cause special logic in my common observer. Finally, I make a special Map function for this emptyBodyResponse.

    public static Function<BaseResponse<EmptyResponse>, EmptyResponse> unwrapEmptyResponse () {
        return baseResponse -> {
            if (baseResponse.getCode().equals(Constants.SUCCESS_CODE)) {
                return new EmptyResponse();
            } else if (baseResponse.getCode().equals(Constants.USER_NOT_LOGGED_IN)) {
                throw new UserNotLoginException(baseResponse.getMsg());
            }
            throw new UnknownServerException(baseResponse.getMsg());
        };
    }

how to handle actions, I mean Observable needs datas to be streamed but I dont have data I just wanted to call a method that do tasks??
What Should I do??

Was this page helpful?
0 / 5 - 0 ratings

Related issues

yubaokang picture yubaokang  ·  3Comments

gfx picture gfx  ·  3Comments

archenroot picture archenroot  ·  3Comments

aballano picture aballano  ·  3Comments

midnight-wonderer picture midnight-wonderer  ·  3Comments