Robospice - Exception never caught in the RequestListener failure method

100 views
Skip to first unread message

Akshat Joshi

unread,
Aug 27, 2015, 2:41:07 AM8/27/15
to RoboSpice

I have an android app which uses Robospice with Google HTTP client to send RESTful request to a server. All works fine if result is successfully returned but if an exception is returned from my service, the Robospice listener doesn't catch the exception.

public final class FBUserSaveListener implements RequestListener<HttpResponse> {

        @Override
        public void onRequestFailure( SpiceException spiceException ) {

            if(progressDialog.isShowing())
            {
                progressDialog.dismiss();
            }

            Toast.makeText(getActivity(),
                    "Error: " + spiceException.getMessage(), Toast.LENGTH_SHORT)
                    .show();
            Intent i = new Intent(getActivity(), ErrorActivity.class);
            startActivity(i);
        }

        @Override
        public void onRequestSuccess(HttpResponse response) {

                if (progressDialog.isShowing()) {
                    progressDialog.dismiss();
                }
            if(response.getStatusCode() == AppConstants.HTTP_CODE_CREATED_201) {
                Intent intent = new Intent(getActivity(), PoolMainActivity.class);
                startActivity(intent);
            }
            else{
                //Request was sent successfully but the response was wrong
                // Redirect to error page
                Intent i = new Intent(getActivity(), ErrorActivity.class);
                startActivity(i);
            }
        }


    }

In the above code, when the external service returns an exception, the onRequestFailure() is not hit at all.

My request is :

public HttpResponse loadDataFromNetwork() throws Exception{

        String url = context.getString(R.string.BASE_SERVICE_URL) + context.getString(R.string.USER_FB_LOGIN_SAVE);

        HttpRequest request = getHttpRequestFactory()//
                .buildPostRequest(new GenericUrl(url), ByteArrayContent.fromString("application/json", fbLoginBeanJson));
        request.setParser(new com.google.api.client.json.jackson2.JacksonFactory().createJsonObjectParser());
         return request.execute();


    }

Did I miss something in the Robospice implementation of RESTful services ?


Thanks in advance.

Stéphane NICOLAS

unread,
Aug 27, 2015, 3:30:26 AM8/27/15
to robo...@googlegroups.com

I am not sure to understand what an error is for you. It looks like you got some error handling in on success.

What kind of error do you expect to trigger the request failure of the listener ?

S.

--
Vous recevez ce message, car vous êtes abonné au groupe Google Groupes "RoboSpice".
Pour vous désabonner de ce groupe et ne plus recevoir d'e-mails le concernant, envoyez un e-mail à l'adresse robospice+...@googlegroups.com.
Pour obtenir davantage d'options, consultez la page https://groups.google.com/d/optout.

Akshat Joshi

unread,
Aug 27, 2015, 4:42:01 AM8/27/15
to RoboSpice
Hi Stephane ,

To give a background. My android app POSTs a request to my server via RESTful service i.e. Jersey. 
Also, on this request, my server can return an exception. I want to catch this exception in my Android app. 

Till where I understand , all exceptions coming from the server, will be cast to SpiceException and the method onRequestFailure( SpiceException spiceException ) will be triggered. But my onRequestFailure is not getting triggered at all. Server is successfully sending an exception.

Android request via Google HTTP client :

public HttpResponse loadDataFromNetwork() throws Exception{

String url = context.getString(R.string.BASE_SERVICE_URL) + context.getString(R.string.USER_FB_LOGIN_SAVE);

HttpRequest request = getHttpRequestFactory()//
.buildPostRequest(new GenericUrl(url), ByteArrayContent.fromString("application/json", fbLoginBeanJson));
request.setParser(new com.google.api.client.json.jackson2.JacksonFactory().createJsonObjectParser());
return request.execute();


}

My server returns the exceptions as :

@Override
    public Response toResponse(BaseException ex) {

        return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
                .entity(
                        new ErrorMessage(
                                ex.getMessage(),
                                Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(),
                                500,
                                ApplicationConstants.NOT_AVAILABLE,
                                ApplicationConstants.NOT_AVAILABLE)
                        )
                .type(MediaType.APPLICATION_JSON).
                build();

    }

I even tried throwing a SpiceException manually, even after catching the exception when request.execute() is triggered. Still the onRequestFailure is not triggered. 

Did I implement it wrong? Can you guide please.

Thanks,
Akshat.

Stéphane NICOLAS

unread,
Aug 27, 2015, 8:15:48 AM8/27/15
to robo...@googlegroups.com

I think I get it.
The problem is that there is a confusion here about what you say an error is.

If you send a request, the server :
* returns a status code
* returns a json
Both in case of an error and a success...

So what you call an error at the application level is indeed a success at the network level.

To deal with that, some framework, like retrofit, expect a 200 return code and nothing else. The rest will be errors. In your case, you use Google httpclient. I have not used it for a while, but I think you should do the following :

In your spice request. After the execute request, get the status code and get the data. If it works (200& return data) then return the pojo directly from your request, your app doesn't want to care about an httpresponse what it wants is data. If the response code is not 200, then parse the json build an exception and throw it.

Rs is designed to let you play at a higher level. In your case you return a http response, but you will always get one, even with a 404 request !

S.

Akshat Joshi

unread,
Aug 27, 2015, 10:18:38 AM8/27/15
to RoboSpice
Thanks, You are correct and I did something in similar lines. I had done this before :-

HttpResponse response;
try {
response = request.execute();
} catch (HttpResponseException hre) {
throw new SpiceException("Something went wrong ...");
}
if (response.getStatusCode() == HttpStatus.SC_INTERNAL_SERVER_ERROR) {
throw new SpiceException("Something went wrong ...");
}
return response;


Google HTTP client itself throws an HTTPResponseException if the Response is not having the success status code. As above, I catch it and throw a SpiceException. Works well till here but then my onRequestFailure() is never hit after this point.
Maybe I implemented it wrong? How do I make the onRequestFailure() to be invoked ?

Thanks,
Akshat.

Stéphane NICOLAS

unread,
Aug 27, 2015, 10:20:54 AM8/27/15
to robo...@googlegroups.com
Are you throws executed ?

--

Akshat Joshi

unread,
Aug 27, 2015, 10:23:43 AM8/27/15
to robo...@googlegroups.com
Yes, my throw new SpiceException() is getting hit.

--
Vous recevez ce message, car vous êtes abonné à un sujet dans le groupe Google Groupes "RoboSpice".
Pour vous désabonner de ce sujet, visitez le site https://groups.google.com/d/topic/robospice/-u3QPRGqBBo/unsubscribe.
Pour vous désabonner de ce groupe et de tous ses sujets, envoyez un e-mail à l'adresse robospice+...@googlegroups.com.

Akshat Joshi

unread,
Aug 27, 2015, 10:24:55 AM8/27/15
to robo...@googlegroups.com
Here is my request class :-

public class FBUserSaveRequest extends GoogleHttpClientSpiceRequest<HttpResponse> {

private String fbLoginBeanJson;
private Context context;

public FBUserSaveRequest(String fbLoginBeanJson, Context context) {
super(HttpResponse.class);
this.fbLoginBeanJson = fbLoginBeanJson;
this.context = context;
}

@Override
    public HttpResponse loadDataFromNetwork() throws Exception {

String url = context.getString(R.string.BASE_SERVICE_URL) + context.getString(R.string.USER_FB_LOGIN_SAVE);

HttpRequest request = getHttpRequestFactory()//
.buildPostRequest(new GenericUrl(url), ByteArrayContent.fromString("application/json", fbLoginBeanJson));
request.setParser(new com.google.api.client.json.jackson2.JacksonFactory().createJsonObjectParser());

Stéphane NICOLAS

unread,
Aug 27, 2015, 10:26:53 AM8/27/15
to robo...@googlegroups.com
That it very very very strange. 
Also
1) I would not throw a spice exception, RS does but you should not. Use a more meaning full exception at your level
2) when you catch and re-throw, wrap the caught exception, always: new Exception("", caughtException)

I am really clueless, this should work.

Akshat Joshi

unread,
Aug 27, 2015, 10:29:07 AM8/27/15
to robo...@googlegroups.com
Agreed. I am throwing it just to show you why this scenario acting this way.
Not sure what I missed :(
Must be something small

Stéphane NICOLAS

unread,
Aug 27, 2015, 1:59:53 PM8/27/15
to robo...@googlegroups.com
Akshat, try returning the parsed datas as a pojo. You should not return a http response, your network layer is leaking into the rest of your app, it's not what you want. You want your app to be network and network library agnostic. 

Encapsulate and isolate network layer classes and don't make them visible to the rest of the app.

So, try parsing the stuff returned from the server and throw an exception if anything goes wrong.

I don't think it's related to the problem you face, but it's the way it should be done

S.

Akshat Joshi

unread,
Aug 30, 2015, 7:24:16 AM8/30/15
to RoboSpice
Hi Stephane,

Sorry for late reply as I was unwell. I managed to solve this by debugging my fragment's life cycle. 
I realized that the spiceManager was getting cleared due to the changes in my fragment's life cycle. Saw your FAQ section it helped me a lot.
Made the spiceManager start and end in the onAttach and onDetach methods respectively.

Thank you so much :)

-Akshat
Reply all
Reply to author
Forward
0 new messages