Le printemps Reste Modèle d'utilisation causes EOFException
Je reçois java.io.EOFException
's lors de l'utilisation de REPOS du Ressort de modèle sur Android.
La stacktrace cause se lit comme suit:
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
Un autre similaire 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
C'est tout ce qui se passe sur Android 4.1.2, installé sur ma tablette Xoom.
Le problème apparaît et disparaît. Ce n'est pas déclenchée par les demandes soit. La partie serveur est en cours d'exécution sur une machine sur le réseau local. Lorsque j'essaie de lancer les Appels d'API à travers curl
, il fonctionne très bien.
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);
}
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;
}
Le Reste du Modèle est configuré comme ceci:
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);
L'appel de l'API en question qui s'est écrasé ici est décrit dans l'Android annotations en fonction de l'interface:
@Post("/user/memberships")
@Accept(MediaType.APPLICATION_JSON)
CompanyApiResponse saveGroupMembership(UserGroupMembership membership) throws RestClientException;
Choses que j'ai essayé:
- Retiré LoggingInterceptor
- Appelé tous les appels d'API par CURL
- Retiré appel BufferingClientHttpRequestFactory - Aidé un peu mais l'erreur persiste.
- Testé sur Android 2.3 - l'erreur ne peut pas être reproduit
J'ai lu sur différents forums postes, les expressions du FOLKLORE exception semble apparaître si les Url sont incorrectes, dont j'ai vérifié dans ce cas.
A noter également, une fois que les expressions du FOLKLORE Exception se produit, l'appel ne soit pas atteint, même du côté serveur.
Où serait un bon point pour continuer la recherche d'un correctif? Est-ce un Android 4.1 inconvénients?
Pendant le débogage de ce problème, j'ai aussi trouvé https://jira.springsource.org/browse/ANDROID-102 qui m'a empêché de voir l'erreur réelle (EOF) avant.
Mise à jour: Viens de trouver http://code.google.com/p/google-http-java-client/issues/detail?id=116 - c'est peut-être lié.
Le correctif est également décrite dans le https://codereview.appspot.com/6225045/ - donc il pourrait avoir été fusionnés pour 4.1.
- Note: ANDROID-102 est résolu dans github.com/ened/spring-android
- Comment puis-je obtenir ce correctif dans mon projet? J'ai téléchargé l'instantané à partir de novembre 26th, mais c'est toujours pas ça...
Vous devez vous connecter pour publier un commentaire.
Ce un peu moi aussi, l'exécution de Jelly Bean 4.2. Après des recherches, il semble que ce qui se passe en raison d'une combinaison de Keep-Alive mis et l'aide de la norme J2SE Client HTTP, qui je crois est HttpURLConnection.
Il y a 2 solutions que je peux confirmer sont corrects.
1) éteindre (Keep-Alive).
Pour moi, la solution donnée à Sébastien réponse, Système.setProperty("http".keepAlive", "false"); n'a pas fonctionné. J'ai eu à utiliser
et d'envoyer les en-têtes dans un HttpEntity dans le RestTemplate.
Comme mentionné, cette solution pourrait avoir un impact sur les performances
2) Modifier le Client HTTP.
Au Printemps pour Android (testé sur la version 1.0.1.LIBÉRATION, mais qui pourraient l'être dans les versions antérieures trop) la valeur par défaut du Client HTTP pour un RestTemplate instance est déterminée par la version d'Android sur l'appareil. API 9 ou plus récent utilise HttpURLConnection, âgés utilise HTTPClient. Pour définir explicitement le client à l'ancien, l'utilisation
Plus d'informations peuvent être trouvées ici: http://static.springsource.org/spring-android/docs/1.0.1.RELEASE/reference/htmlsingle/#d4e34
Je ne sais pas quel impact cela aura sur la performance, mais je suppose que c'est plus performant qu'une application qui ne fonctionne pas.
De toute façon, l'espoir qui aide quelqu'un. Je viens de perdre une semaine sauvages-goose-la quête de ce une.
http://code.google.com/p/google-http-java-client/issues/detail?id=116 contient une solution de contournement dans le dernier commentaire:
Une fois appliquée, l'erreur a disparu.
Il semble qu'il n'est pas entièrement liée à de Printemps, mais un JB problème.
Récemment, j'ai été confronté à ce problème et sera en mesure de résolu ce problème après la définition des en-têtes avec le morceau de code suivant :