春节休息模板的使用会导致EOFException类模板、春节、EOFException

2023-09-13 02:27:34 作者:也許丶我只是壹個過客

我收到 java.io.EOFException 使用在Android春REST模板当s。

I'm receiving java.io.EOFException's when using Spring REST template on Android.

该堆栈跟踪原因读取这样的:

The stacktrace cause reads like this:

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

另一个类似的堆栈跟踪:

Another similar stacktrace:

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

这是一切都发生在Android 4.1.2,安装在我的Xoom平板电脑。

This is all happening on Android 4.1.2, installed on my Xoom tablet.

问题出现和消失。它不是由长报文来触发两种。服务器部分是一台机器上的本地网络内运行。当我尝试运行通过 API调用卷曲,它工作得很好。

The problem appears and disappears. It's not triggered by long requests either. The server part is running on a machine within the local network. When I try to run the API Calls through curl, it works just fine.

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

LoggingClientHtt prequestInterceptor

/** {@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;
}

剩下的模板配置是这样的:

The Rest Template is configured like this:

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

在讨论的API调用在这里坠毁在Android注释描述界面:

The API call in question that crashed here is described in the Android annotations based interface:

@Post("/user/memberships")
@Accept(MediaType.APPLICATION_JSON)
CompanyApiResponse saveGroupMembership(UserGroupMembership membership) throws RestClientException;

我试过

东西:

Things I've tried:

删除LoggingInterceptor 在调用此卷曲所有API调用 在删除了通话BufferingClientHtt prequestFactory - 帮了一点,但仍然出现错误 。 在测试它在Android 2.3 - 的错误不能被复制 Removed LoggingInterceptor Called all API calls by CURL Removed call BufferingClientHttpRequestFactory - Helped a little but the error still occurs. Tested it on Android 2.3 - the error cannot be reproduced

我一直在阅读各种论坛的帖子中,EOF异常看来,如果网址是不正确的,这是我在这种情况下,仔细检查了出现。

I've been reading various forums posts, the EOF exception seems to appear if URLs are incorrect, which I double checked in this case.

另外值得注意的,一旦EOF异常发生时,电话甚至没有到达服务器端。

Also of note, once the EOF Exception occurs, the call not even reaches the server side.

在哪里将是一个很好的点,继续寻求解决?这是一款Android 4.1的不便?

Where would be a good point to continue the search for a fix? Is this a Android 4.1 inconvenience?

在调试这个问题,我还发现https://jira.springsource.org/browse/ANDROID-102其中$ P $从之前看到真正的错误(EOF)pvented我。

While debugging this issue, I also found https://jira.springsource.org/browse/ANDROID-102 which prevented me from seeing the real error (EOF) before.

更新:刚刚发现http://$c$c.google.com/p/google-http-java-client/issues/detail?id=116 - 这可能与

Update: Just found http://code.google.com/p/google-http-java-client/issues/detail?id=116 - it might be related.

该修复程序也 HTTPS概述 - 所以它可能已经被合并为4.1

The fix is also outlined in https://codereview.appspot.com/6225045/ - so it might've been merged for 4.1.

推荐答案

这一位我为好,运行果冻豆4.2。经过研究,似乎它的发生是因为保持活动的组合被设置和使用标准的J2SE HTTP客户端,我相信这是HttpURLConnection的。

This one bit me as well, running Jelly Bean 4.2. After researching, it seems that it's happening because of a combination of Keep-Alive being set and using the standard J2SE HTTP Client, which I believe is HttpURLConnection.

有2的解决方案,我可以证实是正确的。

There are 2 solutions that I can confirm are correct.

1)关闭保持活动。 对我来说,在塞巴斯蒂安的答案给出的解决方案, System.setProperty(http.keepAlive,假); 没有工作。我不得不使用

1) Switch off Keep-Alive. For me, the solution given in Sebastian's answer, System.setProperty("http.keepAlive", "false"); didn't work. I had to use

HttpHeaders headers = new HttpHeaders();
headers.set("Connection", "Close");

和在RestTemplate的HttpEntity发送的报头。 如前所述,这种解决方案可能会对性能产生影响。

and send those headers in an HttpEntity in the RestTemplate. As mentioned, this solution could have an impact on performance

2)更改HTTP客户端。 在春季为Android(上1.0.1.RELEASE测试,但可能是在早期版本中太)的默认HTTP客户端的RestTemplate实例搭载Android的设备上的版本确定。 API 9或更高版本使用的HttpURLConnection,老年采用了HTTPClient。为了客户明确设置为旧的,用

2) Change the HTTP Client. In Spring for Android (tested on 1.0.1.RELEASE, but could be in earlier releases too) the default HTTP Client for a RestTemplate instance is determined by the version of Android on the device. API 9 or newer uses HttpURLConnection, older uses HTTPClient. To explicitly set the client to the old one, use

restTemplate.setRequestFactory(new HttpComponentsClientHttpRequestFactory());

更多信息可以在这里找到:http://static.springsource.org/spring-android/docs/1.0.1.RELEASE/reference/htmlsingle/#d4e34 我不知道什么样的影响,这将有表现,但我想这是不是一个应用程序无法正常工作更好的性能。

More info can be found here: http://static.springsource.org/spring-android/docs/1.0.1.RELEASE/reference/htmlsingle/#d4e34 I'm not sure what impact this will have on performance, but I guess it's more performant than an app that doesn't work.

总之,希望可以帮助别人。我只是浪费了一个星期野生鹅追这一轮下来。

Anyway, hope that helps someone. I just wasted a week wild-goose-chasing this one down.

 
精彩推荐
图片推荐