Ziem Ziem - 6 months ago 69
Android Question

Retrofit doesn't trigger onError when using custom ErrorHandler

I'm using Retrofit 1.9.0, RxJava 1.0.10, RxAndroid 0.24.0 and OkHttp 2.4.0. When I'm setting custom ErrorHandler RxJava Subscriber methods aren't triggered. Why? Is it possible to change this behaviour?

I'm attaching source code.

Initialization:

HttpClient:

OkHttpClient httpClient = new OkHttpClient();
httpClient.setHostnameVerifier(...); // allow all

try {
httpClient.setSslSocketFactory(...);
} catch (NoSuchAlgorithmException | KeyManagementException e) {
e.printStackTrace();
}


RestAdapter:

Gson gson = new GsonBuilder().setDateFormat("yyyy-MM-dd'T'HH:mm:ssZ").create();

RestAdapter restAdapter = new RestAdapter.Builder()
.setEndpoint(BASE_API_URL)
.setLogLevel(RestAdapter.LogLevel.FULL)
.setClient(httpClient)
.setRequestInterceptor(new RequestInterceptor() {
@Override
public void intercept(RequestFacade request) {
request.addHeader("Accept-Language", Locale.getDefault().getLanguage());
}
})
.setConverter(new GsonConverter(gson))
.setErrorHandler(new CustomErrorHandler(this))
.build();

Api api = restAdapter.create(Api.class);


Custom ErrorHandler:

public class CustomErrorHandler implements ErrorHandler {
private final Context mContext;

public UniversalErrorHandler(Context context) {
mContext = context;
}

@Override
public Throwable handleError(RetrofitError cause) {
String errorMessage;

if (cause.getKind() == RetrofitError.Kind.NETWORK) {
errorMessage = mContext.getString(R.string.no_network_connection);
} else {
if (cause.getResponse() == null || cause.getResponse().getStatus() == 500) {
errorMessage = mContext.getString(R.string.error_contacting_server);
} else {
errorMessage = mContext.getString(R.string.unknown_error);
}
}

return new Exception(errorMessage, cause);
}
}


Usage:

Observable<List<Object>> observable = api.getObjects();
observable
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Subscriber<List<Object>>() {
@Override
public void onCompleted() {
Timber.i("onCompleted");
}

@Override
public void onError(Throwable e) {
Timber.e(e, "onError");
}

@Override
public void onNext(List<Object> objects) {
Timber.i("onNext %d", objects.size());
}
});

Answer

I removed this line from the code listing:

Timber.e("Error: %s, %d", cause.getMessage(), cause.getResponse().getStatus());

getStatus() was causing NullPointerException because response was null... I overlooked it because there wasn't any log in logcat.

onError() will not be invoked if runtime exception is thrown from handleError() method.