Seb*_*oth 36 spring android eof android-annotations
我java.io.EOFException在Android上使用Spring REST模板时收到了.
stacktrace原因如下:
Caused by: java.io.EOFException
at libcore.io.Streams.readAsciiLine(Streams.java:203)
at libcore.net.http.HttpEngine.readResponseHeaders(HttpEngine.java:560)
at libcore.net.http.HttpEngine.readResponse(HttpEngine.java:813)
at libcore.net.http.HttpURLConnectionImpl.getResponse(HttpURLConnectionImpl.java:274)
at libcore.net.http.HttpURLConnectionImpl.getResponseCode(HttpURLConnectionImpl.java:486)
at org.springframework.http.client.SimpleClientHttpResponse.getRawStatusCode(SimpleClientHttpResponse.java:49)
at org.springframework.http.client.SimpleClientHttpResponse.getStatusCode(SimpleClientHttpResponse.java:55)
at org.springframework.http.client.BufferingClientHttpResponseWrapper.getStatusCode(BufferingClientHttpResponseWrapper.java:47)
at com.company.util.LoggingClientHttpRequestInterceptor.intercept(LoggingClientHttpRequestInterceptor.java:33)
at org.springframework.http.client.InterceptingClientHttpRequest$RequestExecution.execute(InterceptingClientHttpRequest.java:81)
at com.company.api.interceptor.AuthTokenInterceptor.intercept(AuthTokenInterceptor.java:51)
at org.springframework.http.client.InterceptingClientHttpRequest$RequestExecution.execute(InterceptingClientHttpRequest.java:81)
at org.springframework.http.client.InterceptingClientHttpRequest.executeInternal(InterceptingClientHttpRequest.java:67)
at org.springframework.http.client.AbstractBufferingClientHttpRequest.executeInternal(AbstractBufferingClientHttpRequest.java:46)
at org.springframework.http.client.AbstractClientHttpRequest.execute(AbstractClientHttpRequest.java:63)
at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:475)
... 14 more
Run Code Online (Sandbox Code Playgroud)
另一个类似的堆栈跟踪:
org.springframework.web.client.ResourceAccessException: I/O error: null; nested exception is java.io.EOFException
at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:490)
at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:438)
at org.springframework.web.client.RestTemplate.exchange(RestTemplate.java:414)
at com.company.api.ApiClient_.logLoginAttempt(ApiClient_.java:299)
at com.company.security.CompanyAuthenticationService$2.onCreateCall(CompanyAuthenticationService.java:206)
at com.company.api.SafeApiCall.doInBackground(SafeApiCall.java:49)
at com.company.api.SafeApiCall.doInBackground(SafeApiCall.java:22)
at android.os.AsyncTask$2.call(AsyncTask.java:287)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305)
at java.util.concurrent.FutureTask.run(FutureTask.java:137)
at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:230)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1076)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:569)
at java.lang.Thread.run(Thread.java:856)
Caused by: java.io.EOFException
at libcore.io.Streams.readAsciiLine(Streams.java:203)
at libcore.net.http.HttpEngine.readResponseHeaders(HttpEngine.java:560)
at libcore.net.http.HttpEngine.readResponse(HttpEngine.java:813)
at libcore.net.http.HttpURLConnectionImpl.getResponse(HttpURLConnectionImpl.java:274)
at libcore.net.http.HttpURLConnectionImpl.getResponseCode(HttpURLConnectionImpl.java:486)
at org.springframework.http.client.SimpleClientHttpResponse.getRawStatusCode(SimpleClientHttpResponse.java:49)
at org.springframework.http.client.SimpleClientHttpResponse.getStatusCode(SimpleClientHttpResponse.java:55)
at org.springframework.http.client.BufferingClientHttpResponseWrapper.getStatusCode(BufferingClientHttpResponseWrapper.java:47)
at org.springframework.web.client.DefaultResponseErrorHandler.hasError(DefaultResponseErrorHandler.java:46)
at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:476)
... 13 more
Run Code Online (Sandbox Code Playgroud)
这一切都发生在安装在我的Xoom平板电脑上的Android 4.1.2上.
问题出现并消失.它也不是由长期请求引发的.服务器部分正在本地网络中的计算机上运行.当我尝试运行API调用时curl,它运行正常.
AuthTokenInterceptor:
@Override
public ClientHttpResponse intercept(HttpRequest request, byte[] data, ClientHttpRequestExecution execution) throws IOException {
HttpHeaders headers = request.getHeaders();
if (!StringUtils.isEmpty(mAuthToken)) {
headers.add((mIsOAuth ? "Authorization" : "authToken"), (mIsOAuth ? "Bearer " : "") + mAuthToken);
}
return execution.execute(request, data);
}
Run Code Online (Sandbox Code Playgroud)
LoggingClientHttpRequestInterceptor:
/** {@inheritDoc} */
@Override
public ClientHttpResponse intercept(HttpRequest httpRequest, byte[] bytes, ClientHttpRequestExecution clientHttpRequestExecution) throws IOException {
Log.d(TAG, "To : " + httpRequest.getURI());
Log.d(TAG, "Method : " + httpRequest.getMethod().name());
Log.d(TAG, "Data : " + new String(bytes));
for (Object key : httpRequest.getHeaders().keySet()) {
Log.d(TAG, "Header <" + key + ">: " + httpRequest.getHeaders().get(key));
}
final ClientHttpResponse response = clientHttpRequestExecution.execute(httpRequest, bytes);
if (response != null) {
Log.d(TAG, "Response: " + response.getStatusCode());
if (response.getBody() != null) {
Log.d(TAG, "Response: " + convertStreamToString(response.getBody()));
}
} else {
Log.d(TAG, "Response: " + response);
}
return response;
}
Run Code Online (Sandbox Code Playgroud)
Rest模板配置如下:
final RestTemplate template = new RestTemplate(false);
template.getMessageConverters().add(new MappingJacksonHttpMessageConverter());
template.setRequestFactory(new BufferingClientHttpRequestFactory(template.getRequestFactory()));
ApiUtils.addAuthTokenHeaderToRestTemplate(template, mAuthToken, false);
ApiUtils.addRequestLoggingToRestTemplate(template);
Run Code Online (Sandbox Code Playgroud)
在此处崩溃的API调用在基于Android注释的界面中进行了描述:
@Post("/user/memberships")
@Accept(MediaType.APPLICATION_JSON)
CompanyApiResponse saveGroupMembership(UserGroupMembership membership) throws RestClientException;
Run Code Online (Sandbox Code Playgroud)
我试过的事情:
我一直在阅读各种论坛帖子,如果网址不正确,似乎会出现EOF异常,在这种情况下我会仔细检查.
另外值得注意的是,一旦发生EOF异常,呼叫甚至不会到达服务器端.
在哪里继续搜索修复是一个好点?这是Android 4.1的不便之处吗?
在调试此问题时,我还发现了https://jira.springsource.org/browse/ANDROID-102,这使我无法看到之前的真实错误(EOF).
更新:刚刚找到http://code.google.com/p/google-http-java-client/issues/detail?id=116 - 它可能是相关的.
该修补程序也在https://codereview.appspot.com/6225045/中列出- 因此它可能已合并为4.1.
jas*_*der 59
这一点也是我,运行Jelly Bean 4.2.在研究之后,它似乎正在发生,因为Keep-Alive被设置并使用标准的J2SE HTTP Client,我相信它是HttpURLConnection.
我可以确认有两种解决方案是正确的.
1)关闭Keep-Alive.
对我来说,Sebastian的回答中给出了解决方案,System.setProperty("http.keepAlive","false"); 没用.我不得不使用
HttpHeaders headers = new HttpHeaders();
headers.set("Connection", "Close");
Run Code Online (Sandbox Code Playgroud)
并在RestTemplate中的HttpEntity中发送这些标头.
如上所述,此解决方案可能会对性能产生影响
2)更改HTTP客户端.
在Spring for Android(在1.0.1.RELEASE上测试,但也可能在早期版本中),RestTemplate实例的默认HTTP客户端由设备上的Android版本决定.API 9或更新版使用HttpURLConnection,旧版使用HTTPClient.要将客户端显式设置为旧客户端,请使用
restTemplate.setRequestFactory(new HttpComponentsClientHttpRequestFactory());
Run Code Online (Sandbox Code Playgroud)
更多信息可以在这里找到:http://static.springsource.org/spring-android/docs/1.0.1.RELEASE/reference/htmlsingle/#d4e34
我不确定这会对性能产生什么影响,但我猜测它比不起作用的应用程序更高效.
无论如何,希望能有所帮助.我只是浪费了一周的野鹅追逐这一个.
Seb*_*oth 11
http://code.google.com/p/google-http-java-client/issues/detail?id=116包含最新评论中的解决方法:
这与keepAlive连接有点无关.
当我使用: System.setProperty("http.keepAlive","false"); 问题消失了.
但是根据我的理解,保持活动连接会大大提高性能,所以最好不要禁用它们.
我也很遗憾应该禁用旧版本,但我的设备是Jelly Bean.
一旦应用,错误就消失了.
似乎它与Spring并不完全相关,而是一个JB问题.
| 归档时间: |
|
| 查看次数: |
18355 次 |
| 最近记录: |