Tinder / Scarlet

A Retrofit inspired WebSocket client for Kotlin, Java, and Android
Other
3.23k stars 237 forks source link

Couroutines Adapter Error #161

Closed RafalManka closed 3 years ago

RafalManka commented 3 years ago

I am trying to consume my WebSocket service. I implemented it successfully using Rx, but when I am trying to migrate to coroutines, I am experiencing a crash.

dependencies:

implementation 'com.tinder.scarlet:scarlet:0.1.11'
implementation 'com.tinder.scarlet:websocket-okhttp:0.1.11'
implementation 'com.tinder.scarlet:message-adapter-gson:0.1.11'
implementation 'com.tinder.scarlet:stream-adapter-coroutines:0.1.11'

This code:

Scarlet.Builder()
    .webSocketFactory(okHttpClient.newWebSocketFactory(wsBaseUrl))
    .addMessageAdapterFactory(GsonMessageAdapter.Factory())
    .addStreamAdapterFactory(CoroutinesStreamAdapterFactory())
    .build()
    .create<MyService>()
    .myReceiveFunction()
    .onEach {  /* something */ }
    .launchIn(applicationScope)

will cause the application to crash with stacktrace. please don't mind the fact that the package name contains the word stomp, this needs to be changed as I am no longer using that protocol.

Process: pl.rm.androidstomp, PID: 22946
    java.lang.RuntimeException: Unable to create application pl.rm.androidstomp.App: java.lang.NullPointerException: Attempt to invoke virtual method 'kotlinx.coroutines.internal.LockFreeLinkedListNode kotlinx.coroutines.internal.LockFreeLinkedListHead.getPrevNode()' on a null object reference
        at android.app.ActivityThread.handleBindApplication(ActivityThread.java:6612)
        at android.app.ActivityThread.access$1300(ActivityThread.java:233)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1896)
        at android.os.Handler.dispatchMessage(Handler.java:106)
        at android.os.Looper.loop(Looper.java:223)
        at android.app.ActivityThread.main(ActivityThread.java:7523)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:941)
     Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'kotlinx.coroutines.internal.LockFreeLinkedListNode kotlinx.coroutines.internal.LockFreeLinkedListHead.getPrevNode()' on a null object reference
        at kotlinx.coroutines.channels.AbstractSendChannel.getClosedForSend(AbstractChannel.kt:83)
        at kotlinx.coroutines.channels.AbstractSendChannel.isClosedForSend(AbstractChannel.kt:129)
        at kotlinx.coroutines.reactive.SubscriptionChannel.onSubscribe(Channel.kt:85)
        at io.reactivex.internal.subscribers.StrictSubscriber.onSubscribe(StrictSubscriber.java:85)
        at io.reactivex.internal.operators.flowable.FlowableFlatMapMaybe$FlatMapMaybeSubscriber.onSubscribe(FlowableFlatMapMaybe.java:103)
        at io.reactivex.internal.operators.flowable.FlowableObserveOn$ObserveOnSubscriber.onSubscribe(FlowableObserveOn.java:281)
        at io.reactivex.internal.operators.flowable.FlowableOnBackpressureBuffer$BackpressureBufferSubscriber.onSubscribe(FlowableOnBackpressureBuffer.java:90)
        at io.reactivex.processors.PublishProcessor.subscribeActual(PublishProcessor.java:148)
        at io.reactivex.Flowable.subscribe(Flowable.java:14419)
        at io.reactivex.internal.operators.flowable.FlowableOnBackpressureBuffer.subscribeActual(FlowableOnBackpressureBuffer.java:46)
        at io.reactivex.Flowable.subscribe(Flowable.java:14419)
        at io.reactivex.Flowable.subscribe(Flowable.java:14365)
        at io.reactivex.internal.operators.flowable.FlowableDefer.subscribeActual(FlowableDefer.java:41)
        at io.reactivex.Flowable.subscribe(Flowable.java:14419)
        at io.reactivex.internal.operators.flowable.FlowableObserveOn.subscribeActual(FlowableObserveOn.java:56)
        at io.reactivex.Flowable.subscribe(Flowable.java:14419)
        at io.reactivex.internal.operators.flowable.FlowableFlatMapMaybe.subscribeActual(FlowableFlatMapMaybe.java:54)
        at io.reactivex.Flowable.subscribe(Flowable.java:14419)
        at io.reactivex.Flowable.subscribe(Flowable.java:14368)
        at com.tinder.scarlet.utils.FlowableStream.subscribe(Unknown Source:2)
        at kotlinx.coroutines.reactive.ChannelKt.openSubscription(Channel.kt:25)
        at kotlinx.coroutines.reactive.ChannelKt.openSubscription$default(Channel.kt:23)
        at com.tinder.streamadapter.coroutines.ReceiveChannelStreamAdapter.adapt(ReceiveChannelStreamAdapter.kt:14)
        at com.tinder.streamadapter.coroutines.ReceiveChannelStreamAdapter.adapt(ReceiveChannelStreamAdapter.kt:12)
        at com.tinder.scarlet.internal.servicemethod.ServiceMethod$Receive.execute(ServiceMethod.kt:63)
        at com.tinder.scarlet.internal.servicemethod.ServiceMethodExecutor.execute(ServiceMethodExecutor.kt:21)
        at com.tinder.scarlet.internal.Service.execute(Service.kt:18)
        at com.tinder.scarlet.Scarlet$createInvocationHandler$1.invoke(Scarlet.kt:124)
        at java.lang.reflect.Proxy.invoke(Proxy.java:1006)
        at $Proxy3.deviceChanges(Unknown Source)
        at pl.rm.api.networking.internal.websocket.scarlet.ScarletWebSocketService.deviceResponseUpdates(ScarletWebSocketService.kt:35)
        at pl.rm.api.networking.exposed.Networking.observeDevices(Networking.kt:16)
2020-12-28 11:39:32.301 22946-22946/pl.rm.androidstomp E/AndroidRuntime:     at pl.rm.androidstomp.state.device.DeviceSynchronizer.liveUpdates(DeviceSynchronizer.kt:27)
        at pl.rm.androidstomp.state.device.DeviceSynchronizer.start(DeviceSynchronizer.kt:37)
        at pl.rm.androidstomp.App.onCreate(App.kt:16)
        at android.app.Instrumentation.callApplicationOnCreate(Instrumentation.java:1192)
        at android.app.ActivityThread.handleBindApplication(ActivityThread.java:6607)
            ... 8 more

Any idea what I am doing wrong? There is no official documentation as far as I know.

solidogen commented 3 years ago

Scarlet doesn't work with coroutines 1.4.0+ yet. If you downgrade to 1.3.9 this should work.

Sorry if this is not what you wanted to hear, we need to wait for fix to come.

RafalManka commented 3 years ago

nono, this is exactly what I wanted to hear, because it's an easy fix :-p

I replaced

implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.4.2'

with

implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.9'

and now it works correctly

P1NG2WIN commented 3 years ago

You can place last kotlin reactive dependency into your gradle (watch full name in library gradle) and library will work with last coroutines version

solidogen commented 3 years ago

Thanks @P1NG2WIN. This works for me now (1.4.2):

implementation "org.jetbrains.kotlinx:kotlinx-coroutines-reactive:$coroutines_version"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutines_version"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutines_version"