20

On Android, I initially implemented a Retrofit interface like this:

@DELETE(USER_API_BASE_URL + "/{id}")
public void deleteUser(@Path("id") String id, Callback<User> callback);

The server returns 204 NO CONTENT upon a successful deletion. This was causing the callback to trigger failure, with retrofit.RetrofitError: End of input at character 0 of, as it was expecting a User object back with the response.

I then rewrote it like this, using Void instead of User:

@DELETE(USER_API_BASE_URL + "/{id}")
public void deleteUser(@Path("id") String id, Callback<Void> callback);  <-- VOID

But I am getting the same error from the callback. What is the proper way to fix this? Thank you.

ticofab
  • 7,551
  • 13
  • 49
  • 90

3 Answers3

31

Retrofit 2.x no longer has a ResponseCallback as mentioned in the other answer. You want to use a Response<Void> type.

The RxJava declaration:

@PUT Observable<Response<Void>> foo();

The standard declaration:

@PUT Call<Response<Void>> bar();
Will Vanderhoef
  • 779
  • 7
  • 12
  • 2
    But the problem is even if the web service call has an error, it executes success block and not the throwable block – MobileMon Jun 29 '17 at 14:14
  • I am getting " Cannot serialize abstract class okhttp3.ResponseBody" with retrofit and moshi 2.3.0 – Greg Ennis Jul 27 '17 at 18:06
  • @GregEnnis You're using the wrong type, it's Response from `retrofit2.Response` – Sammy Patenotte Jul 28 '17 at 16:53
  • @SammyPatenotte actually this answer is obsolete. In retrofit 2.3.0 using just PUT Call bar() works as expected; no need for Response<> return type. – Greg Ennis Jul 31 '17 at 13:53
  • Mmh that's weird, in my case it doesn't work with only Void, but I'm using it for POST requests, so I'm not sure if that is the reason why – Sammy Patenotte Jul 31 '17 at 20:29
  • @MobileMon I have the same problem, when there is error from the server, the success block is called but not the throwable, did you find any solution for this? – Kostadin Georgiev May 27 '19 at 08:03
  • This answer works out for `@DELETE` for server returning 204. Thanks! – Roon13 Jun 09 '21 at 18:22
9

The solution was pointed out by Jake Wharton in the comments. Use ResponseCallback.

EDIT: this response is no longer valid for Retrofit < 2.

ticofab
  • 7,551
  • 13
  • 49
  • 90
1

This is the kotlin way for the implementation to deal with HTTP 204 and no content.

@DELETE(USER_API_BASE_URL + "/{id}")
suspend fun deleteuser(@HeaderMap headers: Map<String, String>, 
                       @Path("id") id: String)
: Response<Void>
flame3
  • 2,812
  • 1
  • 24
  • 32
  • Using `Response` will be successful for 204 code but will be also successful for 400 code, the throwable block won't be called for 4xx code responses – Victor Feb 16 '22 at 10:23