Question

I'm dealing with an API that I don't control which returns error responses in JSON format, but doesn't return a non-200 response code in that case. Is it still possible to get anything that is an error (as determined by the presence of an "error" property) in the failure callback when using Retrofit? It's safe to assume I can recognise error responses from that API by looking at the message contents.

Was it helpful?

Solution

This is an application-level distinction which means Retrofit doesn't (and shouldn't) care about it.

There's three ways to accomplish what you want, each of which maps to a behavior of Retrofit.

  1. For asynchronous invocation you can use a custom Callback subtype which does the mapping.

    public abstract class MyCallback<T extends MyResponse> implements Callback<T> {
      @Override public final void success(T data, Response response) {
        if (!data.success) {
          success(data);
        } else {
          error(data.error, response);
        }
        // This is just an example of what a potential common handler could look like.
      }
      public abstract void success(T data);
      public abstract void httpError(Error error, Response response);
    }
    
  2. If you are using the experimental RxJava support you should map the Observable through something which extracts the error.

    service.doSomething()
        .map(new Func1<SomethingResponse, SomethingResponse>() {
        })
        .observeOn(AndroidSchedulers.mainThread())
        .subscribe(..);
    
  3. Finally, for synchronous you can obviously check at every call site, but you can also wrap the API.

    public final class WrappedService implements Service {
      private final Service real;
    
      @Override public SomethingResponse doSomething() {
        return handleError(real.doSomething());
      }
    
      private static <T extends MyResponse> T handleError(T data) {
        if (!data.success) {
          throw new SomeException(data.error);
        }
        return data;
      }
    }
    

    (Hint: You can also use a Proxy to do this for every method automatically!)

The important thing to remember here is that Retrofit's responsibility is to map your HTTP API to a Java API. It is not responsible for applying application-level behavior or constraints to the request or response data. That remains your responsibility.

OTHER TIPS

Looks this is possible in the Converter, from the javadoc:

ConversionException - if conversion was unable to complete. This will trigger a call to Callback.failure(retrofit.RetrofitError) or throw a RetrofitError. The exception message should report all necessary information about its cause as the response body will be set to null.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top