Search code examples
kotlinrx-javaretrofit2rx-java2rx-kotlin

main function is dead while rxjava is working. any solution please


I am trying to get access_token with RXjava.

I ran the program and called the function that requests the access_token, but the process finishes with code 0.

I think the main thread is dead while connecting the server

my solution was Thread.sleep(sometime) to give short time to get the response.

and I also tried

val runnable = Runnable{ getToken() }
val thread = Thread(runnable)
thread.run()
thread.join()

but it didn't work..

here is my code below

fun main(args : Array<String>) {
    getToken()

//    Thread.sleep(10000) // it works but don't want to do with this
}



fun getToken() {
    val id = "test"
    val pw = "test"
    println(id + " " + pw)

    val oAuthService = Retrofit.Builder()
        .baseUrl(URL)
        .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
        .addConverterFactory(GsonConverterFactory.create())
        .client(httpClient)
        .build()
        .create(OAuthService::class.java)

    oAuthService.getAccessToken(
        CLIENT_ID,
        CLIENT_SECRET,
        id,
        pw
    ).subscribeOn(Schedulers.io())
        .flatMap {
            when(it.error){
                null -> Single.just(TokenDto.Success(it.access_token?:"", it.expires_int?:0, it.token_type?:"", it.refresh_token?:""))
                else -> Single.just(TokenDto.Failure("failed"))
            }
        }
        .retry { times, throwable ->
            println(throwable)
            times < 3 }
        .subscribeBy(
            onSuccess = {
                println("onSuccess")
                when(it){
                    is TokenDto.Success -> {
                        println("accessToken : ${it.access_token}")
                    }
                    is TokenDto.Failure -> {
                        println("failed : ${it.msg}")
                    }
                }
            },
            onError = {
                println("onError")
            }
        )
}


retrofit

interface OAuthService {

    @FormUrlEncoded
    @POST("oauth2/token")
    fun getAccessToken(
        @Field("client_id") client_id:String,
        @Field("client_secret") client_secret:String,
        @Field("username") username:String,
        @Field("password") password:String
    ):Single<TokenResponse>

Solution

  • Your subscription to getAccessToken is asynchronous. That's mean that subscribeBy returns immediately and then your main thread is terminated because it has nothing to do. You can use blockingSubscribeBy if you have Observable or blockingGet in a case when you use Single. Both of the operators should block the subscription.

    I also want to clarify that blocking is bad, you should avoid it. Specifically, in your situation, it's ok because you want to block the execution in the main function which is kind of "end of the world" of your program.