0

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>
Vinipuh007
  • 364
  • 2
  • 12
aguagu
  • 83
  • 5

1 Answers1

1

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.

Vinipuh007
  • 364
  • 2
  • 12
  • i just found simple way!! just removing ".subscribeOn(Schedulers.io())" let the process use main thread. – aguagu May 22 '19 at 09:37
  • 1
    I see. But you could have a situation when somewhere in your stream there is a scheduler switch which is hidden from you. For this reason, is better to use block operation – Vinipuh007 May 22 '19 at 10:37
  • agree!! thanx a lot – aguagu May 22 '19 at 23:59