2012-10-26 32 views
1

我目前正在使用Resteasy-mobile用於REST(JAXRS)實現的Android應用程序,以及用於JSON序列化的Jackson。後者由Resteasy在後臺完成。Resteasy-mobile中的ClientResponseFailure爲什麼會導致StackOverflowError?解決方法?

Serverside我有一個澤西web服務,也使用傑克遜序列化/從JSON。

兩者RestEasy的客戶端,而webresource實現像這樣的JAXRS註釋的接口:

@Path("/equipment") 
    @Consumes({"application/json"}) 
    @Produces({"application/json"}) 
    public interface AndroidEquipmentResourceIF 
    { 
     @GET 
     public Model getModel(); 

     @GET 
     @Path("/version") 
     public String getVersion(); 

     @GET 
     @Path("/{eId}") 
     public List<Equipment> getEquipmentListWithId(@PathParam("eId") String eId); 
    } 

客戶機側,該界面被加載到一個工廠,並返回與該接口的對象,它與HTTP涉及/ URL /序列化過程時調用一個方法。

當一個具有無效ID的設備實體被調用時,如果找不到該實體,服務器將拋出一個WebApplicationException。 Clientside,這可能會導致該方法返回null。

如果我想用狀態代碼做一些事情,比如404 - Not found401 - Unauthorized,我可能需要響應對象嗎?我認爲Resteasy和Jersey可以在後臺使用Response對象,那麼有沒有辦法通過Resteasy訪問Response對象或狀態代碼?

編輯1:忘了提第二個選項。我注意到有可能將對象包裝在響應對象中。因此,如果我將所有特定的域對象返回類型替換爲Response,並以某種方式將對象包裝在響應中,我可以從Response對象中提取對象?這聽起來不太乾淨,只是爲了能夠看到狀態碼。另外,我想盡量避免手動解析JSON。

EDIT2:發現它能夠攔截WebApplicationException,所述客戶端RestEasy的拋出一個ClientResponseFailure例外,其可以在攔截器捕獲。問題是,這個例外從不拋出?它看起來像卡在一個無限循環的地方。

我得到以下異常:

10-26 10:52:10.048: E/AndroidRuntime(282): Caused by: java.lang.StackOverflowError 
10-26 10:52:10.048: E/AndroidRuntime(282): at java.util.regex.Matcher.reset(Matcher.java:151) 
10-26 10:52:10.048: E/AndroidRuntime(282): at java.util.regex.Matcher.reset(Matcher.java:211) 
10-26 10:52:10.048: E/AndroidRuntime(282): at java.util.regex.Matcher.<init>(Matcher.java:127) 
10-26 10:52:10.048: E/AndroidRuntime(282): at java.util.regex.Pattern.split(Pattern.java:405) 
10-26 10:52:10.048: E/AndroidRuntime(282): at java.util.regex.Pattern.split(Pattern.java:355) 
10-26 10:52:10.048: E/AndroidRuntime(282): at java.lang.String.split(String.java:2125) 
10-26 10:52:10.048: E/AndroidRuntime(282): at org.jboss.resteasy.plugins.delegates.MediaTypeHeaderDelegate.parse(MediaTypeHeaderDelegate.java:33) 
10-26 10:52:10.048: E/AndroidRuntime(282): at org.jboss.resteasy.plugins.delegates.MediaTypeHeaderDelegate.fromString(MediaTypeHeaderDelegate.java:18) 
10-26 10:52:10.048: E/AndroidRuntime(282): at javax.ws.rs.core.MediaType.valueOf(MediaType.java:173) 
10-26 10:52:10.048: E/AndroidRuntime(282): at org.jboss.resteasy.client.core.BaseClientResponse.getMediaType(BaseClientResponse.java:362) 
10-26 10:52:10.048: E/AndroidRuntime(282): at org.jboss.resteasy.client.core.BaseClientResponse.getEntity(BaseClientResponse.java:346) 
10-26 10:52:10.048: E/AndroidRuntime(282): at org.jboss.resteasy.client.core.BaseClientResponse.getEntity(BaseClientResponse.java:319) 
10-26 10:52:10.048: E/AndroidRuntime(282): at org.jboss.resteasy.client.core.BaseClientResponse.getEntity(BaseClientResponse.java:442) 
10-26 10:52:10.048: E/AndroidRuntime(282): at org.jboss.resteasy.client.core.BaseClientResponse.copyFromError(BaseClientResponse.java:94) 
10-26 10:52:10.048: E/AndroidRuntime(282): at org.jboss.resteasy.client.ClientResponseFailure.<init>(ClientResponseFailure.java:32) 
10-26 10:52:10.048: E/AndroidRuntime(282): at org.jboss.resteasy.client.core.BaseClientResponse.createResponseFailure(BaseClientResponse.java:488) 
10-26 10:52:10.048: E/AndroidRuntime(282): at org.jboss.resteasy.client.core.BaseClientResponse.createResponseFailure(BaseClientResponse.java:479) 
10-26 10:52:10.048: E/AndroidRuntime(282): at org.jboss.resteasy.client.core.BaseClientResponse.readFrom(BaseClientResponse.java:384) 
10-26 10:52:10.048: E/AndroidRuntime(282): at org.jboss.resteasy.client.core.BaseClientResponse.getEntity(BaseClientResponse.java:346) 
10-26 10:52:10.048: E/AndroidRuntime(282): at org.jboss.resteasy.client.core.BaseClientResponse.getEntity(BaseClientResponse.java:319) 
10-26 10:52:10.048: E/AndroidRuntime(282): at org.jboss.resteasy.client.core.BaseClientResponse.getEntity(BaseClientResponse.java:442) 
10-26 10:52:10.048: E/AndroidRuntime(282): at org.jboss.resteasy.client.core.BaseClientResponse.copyFromError(BaseClientResponse.java:94) 
10-26 10:52:10.048: E/AndroidRuntime(282): at org.jboss.resteasy.client.ClientResponseFailure.<init>(ClientResponseFailure.java:32) 
10-26 10:52:10.048: E/AndroidRuntime(282): at org.jboss.resteasy.client.core.BaseClientResponse.createResponseFailure(BaseClientResponse.java:488) 
10-26 10:52:10.048: E/AndroidRuntime(282): at org.jboss.resteasy.client.core.BaseClientResponse.createResponseFailure(BaseClientResponse.java:479) 
10-26 10:52:10.048: E/AndroidRuntime(282): at org.jboss.resteasy.client.core.BaseClientResponse.readFrom(BaseClientResponse.java:384) 
10-26 10:52:10.048: E/AndroidRuntime(282): at org.jboss.resteasy.client.core.BaseClientResponse.getEntity(BaseClientResponse.java:346) 
10-26 10:52:10.048: E/AndroidRuntime(282): at org.jboss.resteasy.client.core.BaseClientResponse.getEntity(BaseClientResponse.java:319) 
10-26 10:52:10.048: E/AndroidRuntime(282): at org.jboss.resteasy.client.core.BaseClientResponse.getEntity(BaseClientResponse.java:442) 
10-26 10:52:10.048: E/AndroidRuntime(282): at org.jboss.resteasy.client.core.BaseClientResponse.copyFromError(BaseClientResponse.java:94) 
10-26 10:52:10.048: E/AndroidRuntime(282): at org.jboss.resteasy.client.ClientResponseFailure.<init>(ClientResponseFailure.java:32) 
+0

這可能有助於[http://stackoverflow.com/questions/2022007/jax-jersey-custom-error-code-in-response][1] [1]:http://stackoverflow.com/questions/2022007/jax-jersey-custom-error-code-in-response –

+0

不是真的。這些問題與將自定義錯誤消息添加到Response對象有關,這不是我正在使用的。我正在返回一個對象,它不是一個響應。 – NickL

+1

從服務器方法拋出一個自定義異常(從WebApplicationException繼承)如果ID無效,不適合你的選擇嗎? –

回答

2

得到它的工作方式如下:

RestEasy的移動是JBOSS RestEasy的2.2.1 GA的修剪版本。很多東西已被刪除,以使其在Android上運行。但有點太多被刪除。

我發現,如果一個ClientResponseFailure被拋出,響應其實體轉換爲Byte陣列,並將複印再次讀取到ClientResponseFailure。問題是,修剪後的版本只包含Strings和text/plain的Messagebody讀寫器,而不是字節數組。所以當試圖讀取實體時,它會嘗試拋出一個新的ClientResponseFailure,因爲它無法找到與Byte[]兼容的MessageBodyReader。然後它再次將該實體轉換爲一個字節數組,嘗試再次讀取它,從而進入一個無限循環,以StackOverflowError結尾。

通過從RestEasy的的非修剪版本添加缺少ByteArrayProviderReadFromStream類的類路徑(在org.jboss.resteasy.plugins.providers.ByteArrayProviderorg.jboss.resteasy.util.ReadFromStream),該ClientErrorInterceptorlink)就像一個魅力!

編輯:我說話有點太快,就像一個魅力沒有工作呢。 ResteasyProviderFactory也已被修改以使其在Android中工作。該.getInstance()方法返回保持一個新的實例,因此,如果您註冊一個ClientErrorInterceptor:ResteasyProviderFactory.getInstance().addClientErrorInterceptor(new DataExceptionInterceptor());它不工作。 ProxyFactory將使用ResyasyProviderFactory內部的新實例。

要解決此問題,用於添加攔截器ResteasyProviderFactory,應傳遞給ProxyFactory.create()

像這樣:

ResteasyProviderFactory pf; 
BasicHttpParams params; 

pf = ResteasyProviderFactory.getInstance(); 

pf.addClientErrorInterceptor(new DataExceptionInterceptor()); 

params = new BasicHttpParams(); 
HttpProtocolParams.setVersion(params, 
           HttpVersion.HTTP_1_1); 
HttpProtocolParams.setContentCharset(params, 
            HTTP.DEFAULT_CONTENT_CHARSET); 
HttpProtocolParams.setUseExpectContinue(params, 
             false); 
return ProxyFactory.create(AndroidEquipmentResourceIF.class, 
          ProxyFactory.createUri(requestURI), 
          new ThreadSafeApacheHttpClient4Executor(params), 
          pf); 
相關問題