Java – How do I handle response errors using Retrofit and RxJava/RxAndroid?

How do I handle response errors using Retrofit and RxJava/RxAndroid?… here is a solution to the problem.

How do I handle response errors using Retrofit and RxJava/RxAndroid?

I can’t figure out how to handle makeover and RxAndroid’s response errors. onError() is called when there is a network error or something similar, but I need to be able to get a response to check if there is an authentication error. Instead, what I get is a token with an empty string and I can’t find the reason. What is the best way to fix this?

Currently this is my RxAndroid call.

    Client.getInstance().getService()
            .getToken(usernameET.getText().toString(), passwordET.getText().toString())
            .subscribe(new Subscriber<SiteInfo>() {
                @Override
                public void onCompleted() {

}

@Override
                public void onError(Throwable e) {
                    e.printStackTrace();
                }

@Override
                public void onNext(SiteInfo siteInfo) {
                    Log.d(TAG, "onNext "+ token.toString());
                }
            });

This is my retrofit service

@GET("my_url_here")
Observable<Token> getToken(
        @Query("username") String username,
        @Query("password") String password
);

This is my current restadapter

RestAdapter restAdapter = new RestAdapter.Builder()
            .setLogLevel(RestAdapter.LogLevel.FULL)
            .setEndpoint(BASE_URL)
            .build();

service = restAdapter.create(MyService.class);

This is my token class.

public class Token {
    private String token;

public String getToken() {
        return token;
    }

public void setToken(String token) {
        this.token = token;
    }

@Override
    public String toString() {
        return token;
    }
}

How should I handle this. Can it be done in the RxAndroid section, or do I need to add something to my RestClient or something entirely?

Thank you.

Edit

07-01 06:38:04.562    1680-1793/uk.co.dyolo.thing D/Retrofit﹕ ---> HTTP GET my_website_here
07-01 06:38:04.562    1680-1793/uk.co.dyolo.thing D/Retrofit﹕ ---> END HTTP (no body)
07-01 06:38:04.610    1680-1793/uk.co.dyolo.thing D/Retrofit﹕ <--- HTTP 200 my_website_here (48ms)
07-01 06:38:04.610    1680-1793/uk.co.dyolo.thing D/Retrofit﹕ : HTTP/1.1 200 OK

Solution

I found a solution

First, I extended the Token object to have the wrong property.

public class Token {

private String token;
    private String error;

public String getToken() {
        return token;
    }

public void setToken(String token) {
        this.token = token;
    }

public String getError() {
        return error;
    }

public void setError(String error) {
        this.error = error;
    }

@Override
    public String toString() {
        return token;
    }
}

Then I added an operator to my RxJava chain that checks if the error field is not null. If an error occurs, a custom exception is thrown and calling subscriber onError allows me to handle it.

if (token.getError() != null) {
    throw OnErrorThrowable.from(new UserAuthenticationException(token.getError()));
    }

If there is an error, throwing a custom exception calling subscriber onError allows me to handle it.

if (e instanceof OnErrorThrowable){
    if (e.getCause() instanceof UserAuthenticationException){
        Log.d(TAG, "onError "+e.getCause().getMessage());
    }
    e.getCause().printStackTrace();
}

Related Problems and Solutions