L'utilizzo del model di rest di spring causa EOFException

Sto ricevendo java.io.EOFException quando utilizzo il model Spring REST su Android.

La causa stacktrace legge così:

  • Torcia elettrica in frammento Android - SurfaceView
  • come aprire l'impostazione WifiDisplay da un'altra applicazione?
  • L'authorization ACCESS_COARSE_LOCATION fornisce una precisione della torre di cella su Android
  • Android - Come distriggersre alcune chiavi nella tastiera virtuale
  • Stampare la piramide inversa dei numbers
  • Android - Accesso al database online SQlite
  •  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'altra stacktrace simile:

     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 

    Questo succede tutto su Android 4.1.2, installato sul mio tablet Xoom.

    Il problema appare e scompare. Non è innescato da lunghe richieste. La parte del server è in esecuzione su una macchina all'interno della networking locale. Quando cerco di eseguire le chiamate API tramite l' curl , funziona bene.

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

    Il model di rest è configurato in questo modo:

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

    La chiamata API in questione che è stata arrestata qui è descritta nell'interface basata su annotazioni Android:

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

    Cose che ho provato:

    • Rimozione LoggingInterceptor
    • Chiamata tutte le chiamate API da CURL
    • Rimosso chiamata BufferingClientHttpRequestFactory – Un po 'aiutato ma l'errore si è ancora verificato.
    • Testato su Android 2.3 – l'errore non può essere riprodotto

    Ho letto vari post di forum, sembra che l'exception EOF venga visualizzata se gli URL non sono corretti, che ho doubleto in questo caso.

    Inoltre, una volta che si verifica l'exception EOF, la chiamata non raggiunge neppure il lato server.

    Dovrebbe essere un buon punto per continuare la ricerca di una correzione? È questo un disagio Android 4.1?

    Durante il debug di questo problema, ho anche trovato https://jira.springsource.org/browse/ANDROID-102 che mi ha impedito di vedere l'errore reale (EOF) prima.


    Aggiornamento: solo trovato http://code.google.com/p/google-http-java-client/issues/detail?id=116 – potrebbe essere correlato.

    La correzione è inoltre descritta in https://codereview.appspot.com/6225045/ – in modo che potrebbe essere stato fuso per 4.1.

  • Android. Scorrere 2 listviews insieme
  • Rileva se un dispositivo BLE è connettibile in Android
  • Stile su AutoCompleteTextView a discesa
  • Elenca l'attività con l'intestazione, il piè di pagina e il vuoto tutto visibile
  • Come get il numero di telefono di un telefono Android CDMA?
  • Come impostare la notifica con il suono personalizzato in android
  • 4 Solutions collect form web for “L'utilizzo del model di rest di spring causa EOFException”

    Anche questo mi ha fatto un po ', facendo funzionare Jelly Bean 4.2. Dopo la ricerca, sembra che sta accadendo a causa di una combinazione di Keep-Alive impostata e utilizzando il client standard J2SE HTTP, che credo sia HttpURLConnection.

    Ci sono due soluzioni che posso confermare sono corrette.

    1) Distriggersre Keep-Alive.
    Per me, la soluzione data dalla risposta di Sebastian, System.setProperty ("http.keepAlive", "false"); non funzionava. Ho dovuto usare

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

    e submit tali intestazioni in una HttpEntity nel RestTemplate.
    Come detto, questa soluzione potrebbe avere un impatto sulle performance

    2) Modificare il client HTTP.
    In spring per Android (testato su 1.0.1.RELEASE, ma potrebbe essere anche nelle versioni precedenti) il client HTTP predefinito per un'istanza RestTemplate è determinato dalla versione di Android sul dispositivo. API 9 o più recenti usa HttpURLConnection, utilizza vecchi HTTPClient. Per impostare esplicitamente il client sul vecchio, utilizzare

     restTemplate.setRequestFactory(new HttpComponentsClientHttpRequestFactory()); 

    Ulteriori informazioni possono essere trovate qui: http://static.springsource.org/spring-android/docs/1.0.1.RELEASE/reference/htmlsingle/#d4e34
    Non sono sicuro di quale impatto avrà sulle performance, ma credo che sia più performante di un'applicazione che non funziona.

    Comunque, spero che aiuta qualcuno. Ho solo sprecato una settimana di selvaggina-caccia questa caccia in giù.

    http://code.google.com/p/google-http-java-client/issues/detail?id=116 contiene una soluzione nell'ultimo commento:

    Ciò è in qualche modo collegato in modo sicuro a connessioni keepAlive.

    Quando utilizzo: System.setProperty ("http.keepAlive", "false"); i problemi scompaiono.

    Ma dalla mia comprensione mantenere vive le connessioni sono notevolmente aumentare le performance quindi è meglio non distriggersrli.

    Sono anche convinto che mantenere vivo dovrebbe essere distriggersto per le vecchie versioni, ma il mio dispositivo è Jelly Bean.

    Una volta applicata l'errore è scomparso.
    Sembra che non sia interamente legato alla spring, ma un problema di JB.

    Recentemente ho affrontato questo problema e sarà in grado di risolvere questo problema dopo aver impostato le intestazioni con il seguente codice:

     headers.set("Accept-Language", "en-US,en;q=0.8"); 
     RestTemplate restTemplate = new RestTemplate(); ((SimpleClientHttpRequestFactory)restTemplate.getRequestFactory()).setOutputStreaming(false); restTemplate.postForObject...... 
    L'Android è un fan Android di Google, tutto su telefoni Android, Android Wear, Android Dev e applicazioni Android Games e così via.