1

I'm using Retrofit 2 in my project. I have a problem with below scenario.

When I call to API and server tell me that the request was not executed with the error code is 4xx or 500 with details message of the problem.

But seems that retrofit understands that it's an http error and did not collect the error message from Server.

I see the closely same problem here but it was not resolved my issue.

I completely get response success and I'm sure that there no problem in my implementation.

    @Override
    public void onResponse(Response<CustomResponse> response, Retrofit retrofit) {
    Log.d("Response : ", response.body(), response.code()); // here i got response.body() is null if response code is not 200, if response code is 200 -- it work well as I expected.
    onRequestSuccess(response);
}

I have a look at Response class in retrofit and I see below code:

  private Response(com.squareup.okhttp.Response rawResponse, T body, ResponseBody errorBody) {
       this.rawResponse = checkNotNull(rawResponse, "rawResponse == null");
       this.body = body;
       this.errorBody = errorBody;
  }

And

  public static <T> Response<T> error(ResponseBody body, com.squareup.okhttp.Response rawResponse) {
      return new Response<>(rawResponse, null, body);
  }

Seems that when response code from server was not 200, retrofit understand that it's error and set body as null.

So any one can help to get the "correct" value of response body in this case?

Community
  • 1
  • 1
ThaiPD
  • 3,503
  • 3
  • 30
  • 48

4 Answers4

2

Use something like that:

if(response.isSuccessful()){
    response.body()
} else{
    response.errorBody()
}
klimat
  • 24,711
  • 7
  • 63
  • 70
  • 1
    As I said above, a same question is existing here http://stackoverflow.com/questions/33757619/retrofit-2-null-response-body?lq=1 but in my case response.errorBody().string() return empty string – ThaiPD Jul 06 '16 at 09:31
2

You have to capture the error body and parse it to your errorModel when the server's response isn't correct. For example:

try {
        // call to retrofit
        Response<SimpleAnswerModel> response = call.execute();
        if (response.isSuccess()) {
            // Do something interesting
        } else {
            Converter<ResponseBody, ErrorModel> converter = apiService.getRetrofit().responseBodyConverter(ErrorModel.class, new Annotation[0]);
            ErrorModel errorModel = converter.convert(response.errorBody());
            // it fails!
            resetNewAlarm();
        }

    } catch (Exception e) {
        // connection fails!
        resetNewAlarm();
    }
oskarko
  • 3,382
  • 1
  • 26
  • 26
  • import okhttp3.ResponseBody; import retrofit2.Call; import retrofit2.Converter; import retrofit2.Response; – oskarko Jul 06 '16 at 09:44
0

Try to parse the response like this:

@Override
            public void onResponse(Call<Void> call, Response<Void> response) {
                //hideLoadingDialog();
                if (response.isSuccess()) {

                    Toast.makeText(ProximityFeedbackActivity.this, "Feedback successfully sent", Toast.LENGTH_LONG).show();
                }

            }

            @Override
            public void onFailure(Call<Void> call, Throwable t) {
                //hideLoadingDialog();
                ProximityFeedbackActivity.this.finish();
                startThankYouActivity();
                Log.e(TAG, "Error in Feedback submission " + t.getMessage());
            }
Lips_coder
  • 686
  • 1
  • 5
  • 17
0

As others have said

if(response.isSuccessful()){
    response.body()
} else{
    response.errorBody()
}

is the correct way of handling errors.

In the string() method there is a call to a readString method

  /** Removes all bytes from this, decodes them as {@code charset}, and returns the string. */
  String readString(Charset charset) throws IOException;

Based on the comment response.errorBody().string() will return the error the first time you call it. Successive calls will return an empty string.

Even if you don't have a call in your code but you have a breakpoint and you inspect the value of string() afterwards it will be empty.

andrei
  • 2,934
  • 2
  • 23
  • 36
  • But nulling a errorBody seems very strange, because it returns string but only once. Seems like a spy message that burns after reading. – Ivan Trechyokas Sep 27 '17 at 06:21