Retrofit: Retrofit + RxJava, how to obtain the responses' error body in case 4XX errors

Created on 21 Oct 2015  路  11Comments  路  Source: square/retrofit

I am using retrofit:2.0.0-beta2 with RxJava and i cannot access the response body in the onError method of my subscriber.

        Retrofit retrofit = new Retrofit
                .Builder()
                .baseUrl(ViatoService.baseUrl)
                .client(client)
                .validateEagerly()
                .addConverterFactory(new ToStringConverterFactory())
                .addConverterFactory(MoshiConverterFactory.create())
                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                .build();

Most helpful comment

There are three ways to construct your observable: Observable<BodyType>, Observable<Response<BodyType>>, or Observable<Result<BodyType>>. For the first version, there's nowhere to hang non-200 response information so it is included in the exception passed to onError. For the latter two, the data is encapsulated in the Response object and can be accessed by calling errorBody().

All 11 comments

In case of response code < 200 || code >= 300 (OkHttp handles redirects and so on) RxJavaCallAdapter will emit onError() with HttpException, HttpException contains response with body and other info.

There are three ways to construct your observable: Observable<BodyType>, Observable<Response<BodyType>>, or Observable<Result<BodyType>>. For the first version, there's nowhere to hang non-200 response information so it is included in the exception passed to onError. For the latter two, the data is encapsulated in the Response object and can be accessed by calling errorBody().

Hello.

I know that this post is old, but i Have a little problem, when I am getting the answer if I use ((HttpException) throwable).response().errorBody().string() and later I try to use the line again or assign to another variable, the second value is empty, anybody has been in the same situation?.

Thanks for your help.

@alejantab Once you consume the response body, you can't reuse it anymore. It's a normal behavior. Then store your response body (response().errorBody().string()) in a variable first, then reuse this variable.

    public void onError(Throwable e){
        HttpException error = (HttpException)e;
        String errorBody = error.response().errorBody().string();
       // now,you can do what you want to do ,like parse ....
 }

Hope to help you!

If you want to separate Response Error and Exception, use Response<BaseResponse<String>>
So you can fetch your non 200 response with body in onNext, and exception in onError

Hi guys, i have very similar problem, can you check this question on stackoverflow: https://stackoverflow.com/questions/50945672/retrofit-response-codes-with-rxjava2

@fanjavaid can you please elaborate your version of the solution?

Will love to have a snippet for this. I still couldn't understand how will i manage to get my response body from API in case of an error as onError method only takes in a Throwable.

My server sends custom response in case of error such as

{
    "status": "Failed",
    "httpcode": 400,
    "devMessage": "APICallSuccess",
    "userMessage": "Problems with your input",
    "data": {...}
}

I want to show the userMessage to the user while using Retrofit + RxJava.

Will love to have a snippet for this. I still couldn't understand how will i manage to get my response body from API in case of an error as onError method only takes in a Throwable.

My server sends custom response in case of error such as

{
  "status": "Failed",
  "httpcode": 400,
  "devMessage": "APICallSuccess",
  "userMessage": "Problems with your input",
  "data": {...}
}

I want to show the userMessage to the user while using Retrofit + RxJava.

I want the same but i dont know how to catch response body in java

Sample:

Exception Class

`public class ExcepcionApi {

private int estado;
private String mensaje;
private int codigo;

public ExcepcionApi(int estado, String mensaje, int codigo){
    this.estado = estado;
    this.mensaje = mensaje;
    this.codigo = codigo;
}

.......`

UserBean

`public class UsuarioBean {

@SerializedName("estado")
@Expose
private Integer estado;
@SerializedName("usuario")
@Expose
private Usuario usuario;`

........

The observer

`public DisposableObserver> getObserver(){
return new DisposableObserver>() {

    `  @Override `              

     `   public void onNext(@NonNull Response loginResponse) {`

//HERE is SAVED THE ERROR RESPONSE.
ExcepcionApi excepcionApi = ExcepcionApi.fromResponseBody(loginResponse.errorBody()); Log.d("presenter", excepcionApi.getMensaje());

Was this page helpful?
0 / 5 - 0 ratings

Related issues

Ne1c picture Ne1c  路  3Comments

ramonmoraes8080 picture ramonmoraes8080  路  3Comments

MetaiR picture MetaiR  路  3Comments

SSVerma picture SSVerma  路  3Comments

kkunsue picture kkunsue  路  3Comments