I am writing an application that uses RoboSpice. In the request listener onRequestFailure( SpiceException arg0 ) is there a way to know for sure that the error was a result of a 401 HTTP Error occurred?
I have a back end service, that returns a 401 error when a token expires, when that occurs I need to prompt the user to re-enter their credentials.
Is there anyway to know that a 401 HTTP error specifically occurred?
Below is an example of my request.
public class LookupRequest extends SpringAndroidSpiceRequest <Product> {
public String searchText;
public String searchMode;
public LookupRequest() {
super( Product.class );
}
@Override
public Product loadDataFromNetwork() throws Exception {
String url = String.format("%s/Lookup?s=%s&m=%s", Constants.BASE_URL, searchText, searchMode);
Ln.d("Calling URL: %s", url);
return getRestTemplate().getForObject(url, Product.class );
}
I looked over Spring-Android closer and it seems getRestTemplate().getForObject(...) throws a HttpClientErrorException when a 401 or any network error occurs.
Looking at the Robo Spice for where they catch that exception I found they catch it in RequestProcessor.java in the processRequest function. They pass the Spring-Android exception in as the throwable inside their SpiceException that inherits from Java exception class.
So you just do the following inside your RoboSpice RequestListener to see if it a 401 UNAUTHORIZED exception.
private class MyRequestListener implements RequestListener<RESULT> {
public void onRequestFailure( SpiceException arg0 ) {
if(arg0.getCause() instanceof HttpClientErrorException)
{
HttpClientErrorException exception = (HttpClientErrorException)arg0.getCause();
if(exception.getStatusCode().equals(HttpStatus.UNAUTHORIZED))
{
Ln.d("401 ERROR");
}
else
{
Ln.d("Other Network exception");
}
}
else if(arg0 instanceof RequestCancelledException)
{
Ln.d("Cancelled");
}
else
{
Ln.d("Other exception");
}
};
public void onRequestSuccess( RESULT result ) {
Ln.d("Successful request");
}
}
I am using the google http client with RoboSpice and has the same issue but was easy to solve with request.setThrowExceptionOnExecuteError(false);
and checking the response code on the resulting HttpResponse
object
EDIT: the code snippit as requested
HttpRequest request = getHttpRequestFactory().buildPostRequest(new GenericUrl(URL), content);
request.setThrowExceptionOnExecuteError(false);
HttpResponse response = request.execute();
switch(response.getStatusCode())
{
case HttpStatusCodes.STATUS_CODE_UNAUTHORIZED:
return new MyBaseResponse(responseBody);
default:
throw new RuntimeException("not implemented yet");
}
For those who can't resolve HttpClientErrorException
into a type, and cannot find any documentations online, (that's me), here is my approach:
In my fragment, here is my listener:
private final class MyRequestListener extends RequestListener<MyResponse> {
@Override
public void onRequestFailure(SpiceException spiceException) {
super.onRequestFailure(spiceException);
if (spiceException instanceof NetworkException) {
NetworkException exception = (NetworkException) spiceException;
if (exception.getCause() instance RetrofitError) {
RetrofitError error = (RetrofitError) exception.getCause();
int httpErrorCode = error.getResponse().getStatus();
// handle the error properly...
return;
}
}
// show generic error message
}
}
Hope this maybe helpful to someone.
I would move the whole if
clause into a static function so it can be reused. Just return 0 if exception doesn't match. And I haven't verify if any of the casting can be removed...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With