2013-02-13 12 views
14

RoboSpiceを使用するアプリケーションを作成しています。リクエストリスナーのonRequestFailure(SpiceException arg0)には、エラーが401 HTTPエラーが発生したことを確認する方法がありますか?RoboSpiceを使用すると、例外からHTTPエラーコードを取得できますか?

トークンが期限切れになったときに401エラーを返し、そのときにユーザーに資格情報を再入力する必要があるバックエンドサービスがあります。

特に401 HTTPエラーが発生したことを知っていますか?

以下は私のリクエストの例です。

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); 
} 

答えて

20

私が近づく春のAndroid上で見て、401または任意のネットワークエラーが発生したときにgetRestTemplate()。getForObject(...)はHttpClientErrorExceptionをスローします。そうです

Robo Spiceがその例外をどこで捕まえているのか見ると、processRequest関数内のRequestProcessor.javaでそれを捕まえることがわかりました。彼らは、Java例外クラスから継承したSpiceException内のスロー可能オブジェクトとして、Spring-Android例外を渡します。

したがって、RoboSpice RequestListenerの内部では、401 UNAUTHORIZED例外が発生していないかどうかを確認するだけです。

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"); 
    } 
} 
+3

ステータスコードと 'HttpStatus'を比較するために' equals() 'を使っていくつかの矛盾が発生しています。代わりに私は問題なく比較し始めました: 'exception.getStatusCode()。value()== HttpStatus.SC_BAD_REQUEST'。希望が役立ちます。 – Moritz

+3

'HttpClientErrorException'は型に解決できません。 – KarenAnne

+0

HttpClientErrorExceptionの代わりに、私はHttpResponseExceptionを取得しています – kheit

2

私はRoboSpiceとGoogleのHTTPクライアントを使用して、同じ問題を持っていますが、request.setThrowExceptionOnExecuteError(false);で解決することは容易であり、得られたHttpResponseオブジェクトの応答コードをチェックしています

EDIT:

を要求したとして、コードsnippit Java用のGoogleのHTTPクライアントで
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

一部のコードは大歓迎です。 :) – Snicolas

+0

done - 編集済み – Dori

0

あなたがそうのようにもインターセプトエラー応答することができます:

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); 
    } 
} 
0123を

とあなたのGoogleHttpClientSpiceServiceに:

@Override 
public HttpRequestFactory createRequestFactory() { 
    return AndroidHttp 
     .newCompatibleTransport().createRequestFactory(new InitIntercept()); 
} 
0

それは他の回答のすべてよりもさらに簡単です。

私にとっては、@Scrotosの答えは問題になりました。なぜなら、401が捕まえるためのポイントは、authエンドポイントへの要求を行い、その後再びプライマリリクエストを行うためです。あなたが望むデータや何らかの "本当の"エラーのあるUIに戻るだけです。 コールバック内ではなく、loadDataFromNetwork()の内部で行うべきです。

私はこのようにそれをやった:ここでは、(それは私です)、型にHttpClientErrorExceptionを解決できない、とオンライン任意のドキュメンテーションを見つけることができない人のために

@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

複数の同時リクエストをどのように処理しますか?このコードは複数の認証要求を行います。そうではありません。 – BornToCode

+0

これは、認証ストアの実装によって異なります。私はAccountManagerを使用します。同時要求の1つが401を取得すると、AccountManager内のトークンが更新され、以降のすべての要求はこの時点から適切なトークンを取得します。しかし、私はこのコードで同時リクエストを試みたことはありません –

2

は私のアプローチです:

誰かに

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 
    } 

} 

ホープ、この多分役立つ:私のフラグメントで

は、ここに私のリスナーです。

if節全体を静的関数に移動して再利用することができます。例外が一致しない場合は、単に0を返します。そして、キャストのいずれかが削除できるかどうかを確認していません...

+0

RetrofitErrorとは何ですか?あなたのコードを投稿できますか? – exequielc

+1

RetrofitErrorは、Retrofit 1.6.1で定義されたクラスです。 2.xを使用している場合、それはもう存在しないかもしれません。パス:retrofit-1.6.1-sources.jar!/retrofit/RetrofitError.java パブリッククラスRetrofitError extends RuntimeException {...} –

関連する問題