Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

OnFailure called and IOException thrown but data posted

This is my network request sample

networkAPI.postData(myData).enqueue(new Callback<MyResponse>() {
    @Override
    public void onResponse(Call<MyResponse> call, Response<MyResponse> response) {
         if (response.code() == 201) {
             // success
         }
    }
    @Override
    public void onFailure(Call<MyResponse> call, Throwable t) {

    }
});

It is the request I should call only once as I've one time usable voucher code. If I turn off my network connection immediately or if it disconnects instantly after calling this method, then it moves to onFailure method with IOException in throwable which generally refers connection error, But the point is data posted to server and voucher code has been used and the problem is onFailure method was called here.

I am sure that it is not a parsing failure hence I tried using Void too. Why onResponse is not called even after posting the data. How to overcome such situation?

like image 763
Shree Krishna Avatar asked Jul 13 '18 04:07

Shree Krishna


4 Answers

I don't know what your backend is but in C# WebApi, on the server side, you can check if the client is still connected via Response.IsClientConnected but this flag is only for graceful tcp disconnects i believe. It won't work if the client shuts off his internet suddenly. This is simply due to the nature of http (and underlying tcp)

Also, I think it's worth mentioning that there's always the possibility of the request reaching the server but the response not reaching the client. There's simply no way to guarantee that the server wont process the voucher without the successful response to the client. The client could send the request and as soon as you're ready to return status code 200, the client may disconnect. This should always be considered in web service design.

Best thing to do is to give the client some way of viewing past redeemed vouchers. Or on a page fresh or something you can automatically check if there was a past voucher redemption attempt (via another webservice method) and display a response appropriately.

like image 188
Sal Avatar answered Nov 15 '22 14:11

Sal


I think the retrofit methods are working as expected. This might happen that you have posted some data to your server and even if the internet is connected, your server application is taking too much time to process the request and once the server responded back with a success status, the application side request is timed out. The point is there are several such cases, in which you might face the same problem.

I can think of a graceful solution to this specific problem by building a server-client handshaking about using a voucher. You might consider having a local database setup (it can be any storing mechanism which can be handled locally) tracking the voucher codes that you have tried to use so far. In that case, when a request is initiated, a flag will be generated locally and on getting a successful response from server side the flag is cleared.

Now, what are the advantages of using this special flag indicating if the voucher is used or not? The main advantage is that you can sync the status of availing the voucher later on receiving a broadcast when your internet is connected again. You might consider checking the flag also in application start-up to sync between server and client in case of any prior flag is opened.

The key idea of my answer is to build a server-client handshaking mechanism in which you can confirm if the voucher is availed or not.

like image 31
Reaz Murshed Avatar answered Nov 15 '22 13:11

Reaz Murshed


My random guess is that your response has changed dynamically(may be even null) in your specific error scenario. Since you are expecting an object of type MyResponse, when a dynamically changed response is returned, your retrofit call may not be able to handle the response and hence jumps to the onFailure method. In this case your data gets posted to your backend whereas retrofit gets into onFailure

Possible Solution

First try to find out the response in case where the particular error occurs and try to make a model for it(use void for null)

Try dynamically parsing json by making use of deserialiser to handle the dynamic error response and proper response at run time. Hence by using a deserialiser, you can make your error response(case where data gets posted) also appear in onResponse

like image 22
Navneet Krishna Avatar answered Nov 15 '22 13:11

Navneet Krishna


According to the question i believe you are posting the data correctly with network and when the server tries to give you the response, your system loses connection due to network failure and retrofit gives a failure callback.

Solution

You can call a retry api dialog when the execution reaches onfailure due to network failure and ask the user to send the api again and get the response correctly. So by until and unless the user is given the appropriate response, he will be blocked to move further.

like image 32
fightingCoder Avatar answered Nov 15 '22 15:11

fightingCoder