3

I am consuming an API in Android using Retrofit. The success response looks different to the error/failure response. How can I therefore achieve this?

I currently have something to this affect:

Call<AuthenticateUserResponse> authenticateUser(String id);
Subby
  • 5,370
  • 15
  • 70
  • 125

1 Answers1

6

You can extend your Responses with a base Response and check if there's an error or it's succeed. Here's an example base response bean below:

public class BaseResponse {
    @SerializedName("ResponseCode")
    private int code;
    @SerializedName("ResponseMessage")
    private String message;
    @SerializedName("ResponseText")
    private String text;
}

My api returns ResponseCode, ResponseMessage and ResponseText in every responser and i extend my responses from BaseResponse bean and check if there's an error.

You can modify your responses as your api's return schemes.

Edit: Here's your Response for your Api:

public class Error {
        @SerializedName("ResponseCode")
        private int code;
        @SerializedName("ResponseMessage")
        private String message;
        @SerializedName("ResponseText")
        private String text;
    }

public class YourWrapperResponse {
        @SerializedName("Error")
        private Error error;
        @SerializedName("AuthenticateUserResponse")
        private AuthenticateUserResponse authenticateUserResponse;
    }

And your call will be like:

Call<YourWrapperResponse> authenticateUser(String id);

The example above i gave you is an example of handle business errors which you get in your every successful response. Successful means Http Status 200. Also you do not need to return this Error object in your every response. If there's an error you can return in your response.

In Retrofit 2.0+ you need to check if your request is succeed. Here's an example below about it:

    Call<User> auth = YourApiProvider.getInstance().getServices().auth(userName, passowrd, grantType);
            auth.enqueue(new Callback<User>() {
                @Override
                public void onResponse(Call<User> call, Response<User> response) {
                    if (response.isSuccessful()) {
                        // Here you get a 200 from your server.
                        }
                    } else {
                        // Here you get an authentication error.
                        // You can get error with response.code();
                        // You can get your error with response.errorBody(); 
                        // or you can get raw response with response.raw()
                    }
                }

                @Override
                public void onFailure(Call<User> call, Throwable t) {
                    // Here you get error such as TimeOut etc.
                }
            });

I hope this'll help you. Good Luck!

Edit: You can also use generics to handle base api responses. Here's my another answer about handling generic api responses.

savepopulation
  • 11,736
  • 4
  • 55
  • 80
  • The API that I am using returns an `Error` object when it fails and doesn't show one when it succeeds. Will your approach of subclassing still work? Or will it throw an error saying there's no such object as `Error` when it succeeds? – Subby Jun 06 '16 at 17:25
  • When it succeeds it will map your object. And if there's no error it won't say there's no such object as Error. So i think if you put your Error object it base response you'll not get any trouble. – savepopulation Jun 06 '16 at 17:28
  • It seems like Retrofit is not serializing if the request fails, i.e. 401. If the request succeeds, it serialized. Am I missing some configuration or something? – Subby Jun 07 '16 at 15:27
  • No. in Retrofit 1.9 when you get an http error you get an RetrofitError. In 2.0 you need to check call if response.isSuccessful(). My example above is when you get 200 from your server and your get your business errors in your json response. – savepopulation Jun 07 '16 at 15:32
  • I am using Retrofit 2.0.2 and OkHttp3.3.1. Whenever I call an API, if I get a 401 (which is correct as I haven't authenticated yet), the response.body is always null... And I need the Error object (which is in the response.body) to perform the correct action. How do I fix this? – Subby Jun 07 '16 at 15:36
  • Oops okey you need to handle a http error. Wait i'll edit my answer. – savepopulation Jun 07 '16 at 15:37
  • So I can't get the `Error` object from `response.body().getError()`? Does this mean it won't give me a `repsonse.body()` at all if I get a 401? – Subby Jun 07 '16 at 16:21
  • Yes. 401 is not a successful response. – savepopulation Jun 07 '16 at 16:39
  • For a 401, I still get back a response form the server that tells me exactly why it has failed. it gives me back an Error code as well. How can I get this ? If I look at the errorBody(), I can see the details there but it's not in a format which is useful. – Subby Jun 07 '16 at 16:41
  • I edited my answer. You can get 401 with error.code or you can get message with error.message or raw response or error body. you can convert it to your own objects. – savepopulation Jun 07 '16 at 16:43
  • Ok I think I've found what I simply need to do. I need to deserialise response.errorBody(). Is there a way I can do that? – Subby Jun 07 '16 at 17:06
  • You can use gson. If my answer helped you please accept it. thanks. – savepopulation Jun 07 '16 at 17:22