Search code examples
androidkotlingsonretrofit2okhttp

Retrofit 2 and kotlin: Not deserializing issue: IllegelArgumentException: closed


Hi I am new to retrofit and I am using

implementation 'com.squareup.retrofit2:retrofit:2.6.1'
// JSON Parsing
implementation 'com.google.code.gson:gson:2.8.5'
implementation 'com.squareup.retrofit2:converter-gson:2.1.0'

I am making an API call to login. The call is success(I can see the 200 response in the interceptor I added), but still I am getting onFailure callback in retrofit with java.lang.IllegalStateException: closed as throwable. I added some breakpoints inside Retrofit class and it seems like it is arising while parsing my response. I am also using Kotlin

here is my data class:

data class LoginResponse(
    @SerializedName("payload") @Expose val payload: Payload,
    @SerializedName("status") @Expose val status: Int
)
data class Payload(
    @SerializedName("access_token") @Expose val access_token: String?,
    @SerializedName("expires_at") @Expose val expires_at: String?,
    @SerializedName("name") @Expose val name: String?,
    @SerializedName("org_name") @Expose val org_name: String?,
    @SerializedName("request_at") @Expose val request_at: String,
    @SerializedName("status_message") @Expose val status_message: String
)

Here is how I am creating my retrofit instance:

private val okHttpClient = OkHttpClient.Builder().addInterceptor(Interceptor {
    Log.w("Retrofit@Request", it.request().toString())
    val requestBuilder = it.request().newBuilder()
    requestBuilder.header("Content-Type", "application/json")
    val response = it.proceed(it.request())
    Log.w("Retrofit@Response", response.body()!!.string())  //correct 200 response with json is printed out here
    return@Interceptor response
}).build()

val retrofitInstance: Retrofit
    get() {
        if (retrofit == null) {
            retrofit = Retrofit.Builder()
                .baseUrl(BASE_URL)
                .client(okHttpClient)
                .addConverterFactory(GsonConverterFactory.create())
                .build()
        }
        return retrofit!!
    }

Here is how I am making the call:

loginService.login(logindata).enqueue(object : Callback<LoginResponse> {
                override fun onFailure(call: Call<LoginResponse>, t: Throwable) {
                    Log.d(TAG, "Login failure "+t) //this is getting invoked with java.lang.IllegalStateException: closed
                }

                override fun onResponse(
                    call: Call<LoginResponse>,
                    response: Response<LoginResponse>
                ) {
                    onLoginState.value = true
                }
            })

I spend a lot of time trying to figure out what is happening, could not find what I am doing wrong here. I also tried replacing GSON with Moshi which gave me the same error. Please help me figure out the issue here.

Thanks in advance.


Solution

  • I don't know if this help, but try to read this thread & try to remove your log Log.w("Retrofit@Response", response.body()!!.string()) or replace with the hint in that thread

    // Don't try to use response.body.string() directly. Just using like below:
    ResponseBody responseBody = response.body();
    String content = responseBody.string();
    // Do something with "content" variable
    

    Reason: The string() of body is stored in memory to variable content, so we don't need to care of whether the state is closed.