Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to handle error response with Retrofit 2?

How to handle error response with Retrofit 2 using synchronous request?

I need process response that in normal case return pets array and if request has bad parametrs return error json object. How can I process this two situations?

I am trying to use this tutorial but the main problem is mapping normal and error json to objects.

My normal response example:

[ {
    "type" : "cat",
    "color": "black"
}, 
{
    "type" : "cat",
    "color": "white"
} ]

Error response example:

{"error" = "-1", error_description = "Low version"}

What I got:

    Call<List<Pet>> call = getApiService().getPet(1);
    Response<List<Pet>> response;
    List<Pet> result = null;

    try {
        response = call.execute(); //line with exception "Expected BEGIN_ARRAY but was BEGIN_OBJECT at line 1 column 2 path"
        if(!response.isSuccessful()){
            Error error = parseError(response);
            Log.d("error message", error.getErrorDescription());
        }
        if (response.code() == 200) {
            result = response.body();
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
like image 845
Andrew Evtukhov Avatar asked Apr 10 '17 11:04

Andrew Evtukhov


2 Answers

Retrofit 2 has a different concept of handling "successful" requests than Retrofit 1. In Retrofit 2, all requests that can be executed (sent to the API) and for which you’re receiving a response are seen as "successful". That means, for these requests, the onResponse callback is fired and you need to manually check whether the request is actually successful (status 200-299) or erroneous (status 400-599).

If the request finished successfully, we can use the response object and do whatever we wanted. In case the error actually failed (remember, status 400-599), we want to show the user appropriate information about the issue.

For more details refer this link

like image 184
fightingCoder Avatar answered Sep 30 '22 08:09

fightingCoder


After going through a number of solutions. Am posting it for more dynamic use. Hope this will help you guys.

My Error Response

{
"severity": 0,
"errorMessage": "Incorrect Credentials (Login ID or Passowrd)"
}

Below is as usual call method

private void makeLoginCall() {
    loginCall = RetrofitSingleton.getAPI().sendLogin(loginjsonObject);
    loginCall.enqueue(new Callback<Login>() {
        @Override
        public void onResponse(Call<Login> call, Response<Login> response) {
            if (response != null && response.code() == 200){
                //Success handling
            }
            else if (!response.isSuccessful()){
                mServerResponseCode = response.code();
                Util.Logd("In catch of login else " + response.message());
                /*
                * Below line send respnse to Util class which return a specific error string
                * this error string is then sent back to main activity(Class responsible for fundtionality)
                * */

                mServerMessage = Util.parseError(response) ;
                mLoginWebMutableData.postValue(null);
                loginCall = null;
            }
        }

        @Override
        public void onFailure(Call<Login> call, Throwable t) {
            Util.Logd("In catch of login " + t.getMessage());
            mLoginWebMutableData.postValue(null);
            mServerMessage = t.getMessage();
            loginCall = null;
        }
    });
}

Below Is util class to handle parsing

public static String parseError(Response<?> response){
    String errorMsg = null;
    try {
        JSONObject jObjError = new JSONObject(response.errorBody().string());
        errorMsg = jObjError.getString("errorMessage");
        Util.Logd(jObjError.getString("errorMessage"));
        return errorMsg ;
    } catch (Exception e) {
        Util.Logd(e.getMessage());
    }
    return errorMsg;
}

Below in viewModel observer

private void observeLogin() {
    loginViewModel.getmLoginVModelMutableData().observe(this, login -> {
        if (loginViewModel.getSerResponseCode() != null) {
            if (loginViewModel.getSerResponseCode().equals(Constants.OK)) {
                if (login != null) {
                    //Your logic here
                }
            }
           //getting parsed response message from client to handling class
            else {
                Util.stopProgress(this);
                Snackbar snackbar = Snackbar.make(view, loginViewModel.getmServerVModelMessage(), BaseTransientBottomBar.LENGTH_INDEFINITE).setAction(android.R.string.ok, v -> { });
                snackbar.show();
            }
        } else {
            Util.stopProgress(this);
            Snackbar snackbar = Snackbar.make(view, "Some Unknown Error occured", BaseTransientBottomBar.LENGTH_INDEFINITE).setAction(android.R.string.ok, v -> { });
            snackbar.show();
        }
    });
}
like image 25
Ashok Jangra Avatar answered Sep 30 '22 07:09

Ashok Jangra