Using RoboSpice is there a way to get the HTTP Error Code out of an exception?

前端 未结 5 824
失恋的感觉
失恋的感觉 2021-01-31 11:29

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

相关标签:
5条回答
  • 2021-01-31 12:13

    With google http client for java you can also intercept error responses like so:

    public static class InitIntercept implements 
        HttpRequestInitializer, HttpUnsuccessfulResponseHandler {
    
        @Override
        public boolean handleResponse(
            HttpRequest request, 
            HttpResponse response, 
            boolean retrySupported) throws IOException {
    
            if (response.getStatusCode() == HttpStatusCodes.STATUS_CODE_UNAUTHORIZED) {
                ...
            }
    
            return false;
        }
    
        @Override
        public void initialize(HttpRequest request) throws IOException {
            request.setUnsuccessfulResponseHandler(this);
        }
    }
    

    and in your GoogleHttpClientSpiceService:

    @Override
    public HttpRequestFactory createRequestFactory() {
        return AndroidHttp
            .newCompatibleTransport().createRequestFactory(new InitIntercept());
    }
    
    0 讨论(0)
  • 2021-01-31 12:17

    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");
        }
    }
    
    0 讨论(0)
  • 2021-01-31 12:19

    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");
        }
    
    0 讨论(0)
  • 2021-01-31 12:25

    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...

    0 讨论(0)
  • 2021-01-31 12:27

    It's even easier than all of the other answers.

    For me @Scrotos answer was problematic, because the whole point for the 401 to be caught is to make the request to auth endpoint and then make the primary request again. So that you only return to UI with desired data or some "real" error. So it shouldn't be done inside the callback, but rather inside loadDataFromNetwork() itself.

    I've done it this way:

    @Override
    public SubscriptionsContainer loadDataFromNetwork() {
    
        //...
    
        ResponseEntity<SubscriptionsContainer> response = null;
        try {
            response = getRestTemplate().exchange(
            //your request data                    
            );
        } catch (HttpClientErrorException e) {
            HttpStatus statusCode = e.getStatusCode();
            //check the exception, if it's 401, make call to auth and repeat loadDataFromNetwork()
        }
    
    0 讨论(0)
提交回复
热议问题