kotlinretrofit2eofexception

End of input at line 1 column 1 path $ - Not solved by other solutions


New to Api's.

I had a working API. My Get and post worked. Now only my get works and my post makes my app crash after every post.

Initially when it did work I got a error code of 500. Server side. Since then we have worked on the server and fixed a few other problems, now however - I get my data with a get and no problem occurs. When I post get the following:

    I/System.out: --> POST http://intranet.localnet:777/?q=8&ID=Tab04&p1=0&p2=0000210965
    I/System.out: Content-Length: 0
    I/System.out: --> END POST (0-byte body)
    I/System.out: <-- 200 OK http://intranet.localnet:777/?q=8&ID=Tab04&p1=0&p2=0000210965 
    (745ms)
    I/System.out: Connection: close
    I/System.out: Content-Type: text/html
    I/System.out: Server: Indy/9.00.10
    I/System.out: <-- END HTTP (0-byte body)
    E/AndroidRuntime: FATAL EXCEPTION: main
        Process: com.dispatch.tripsheet, PID: 21559
        java.io.EOFException: End of input at line 1 column 1 path $

I don't know if the rest of the error is necessary "at .com.google...." - so I left that out.

As shown I do get a success of reaching the server, and it does update the db. But my app crashed on each instance.

Below Is my code for my API:

        object RetrofitInstance {
        
            val nullOnEmptyConverterFactory = object : Converter.Factory() {
                fun converterFactory() = this
                override fun responseBodyConverter(type: Type, annotations: Array<out 
        Annotation>, retrofit: Retrofit) = object : Converter<ResponseBody, Any?> {
                    val nextResponseBodyConverter = retrofit.nextResponseBodyConverter<Any?> 
       (converterFactory(), type, annotations)
                    override fun convert(value: ResponseBody) = if (value.contentLength() != 0L) 
        nextResponseBodyConverter.convert(value) else null
                }
            }
            
            val loggingInterceptor: HttpLoggingInterceptor = HttpLoggingInterceptor { message -> 
        // Log the request URL
                println("$message")
            }.setLevel(Level.BODY)
        
            private val httpClient = OkHttpClient.Builder()
                .addInterceptor(loggingInterceptor)
                .build()
        
            private val retrofit by lazy {
                Retrofit.Builder()
                    .baseUrl(BASE_URL)
                    .client(httpClient)
                    .addConverterFactory(nullOnEmptyConverterFactory)
                    .addConverterFactory(GsonConverterFactory.create())
                    .build()
            }
        
            val api: API by lazy {
                retrofit.create(API::class.java)
            }
        
        } 

Below Is my code for my MainViewModelFactory:

        class MainViewModelFactory(private val repository: Repository):  ViewModelProvider.Factory {
            override fun <T : ViewModel?> create(modelClass: Class<T>): T {
                return MainViewModel(repository) as T
            } }

Below Is my code for my MainViewModel:

        fun pushClear(uniqueId: String, DELIVERED: Int = 0, delno: String) {
            viewModelScope.launch {
                val call = repository.pushClear(uniqueId, DELIVERED, delno)
                call.enqueue(object : Callback<Unit> {
                    override fun onResponse(call: Call<Unit>, response: Response<Unit>){
                    }
                    override fun onFailure(call: Call<Unit>, t: Throwable) {
                    }
    
                })
        //            val response = repository.pushClear(uniqueId, DELIVERED, delno)
        //            myPost6.value = response
            }
        }

Below Is my code for my Repository:

        suspend fun pushClear(uniqueId: String, DELIVERED: Int = 0, delno: String): Call<Unit> {
            return RetrofitInstance.api.pushClear(uniqueId, DELIVERED, delno)
        }

Below Is my code for my Post:

        @POST("/?q=8")
        suspend fun pushClear(
            @Query("ID") uniqueId: String,
            @Query("p1") DELIVERED: Int = 0,
            @Query("p2") delno: String
        ): Call<Unit> 

Below Is my code for when I call the use of the POST:

                val repository = Repository()
                val viewModelFactory = MainViewModelFactory(repository)
                viewModel = ViewModelProvider(this, 
                viewModelFactory).get(MainViewModel::class.java)
                viewModel.pushClear(uniqueId,0, DELNO)         

I have seen a lot of similar issues with

End of input at line 1 column 1 path $

I have tried all of there solution but have had no success, which is why I am asking my questions. I have tried the following:

I can change the server to respond {"OK": "Cupcake"}. However, that requires server feedback. Can that be circumvented?


Solution

  • Only skimming your question, I think this general error End of input at... is caused because your code expects some kind of return (a serialised object) from the server after a successful POST. And the deserialiser cannot find any data to produce you the object since the data stream is empty you can see the last line here:

        I/System.out: <-- 200 OK http://intranet.localnet:777/?q=8&ID=Tab04&p1=0&p2=0000210965 
        (745ms)
        I/System.out: Connection: close
        I/System.out: Content-Type: text/html
        I/System.out: Server: Indy/9.00.10
        I/System.out: <-- END HTTP (0-byte body)
    

    0-byte body

    So your code should be changed to remove the expectation that an object will be returned (or change the server to return something).