I'm using restTemplate (from the spring android framework) on my android application to contact a rest server with post, i'm using an AsyncTask to send the request and two classes Request and Response which are POJOs send in Json form.
public class RequestSender extends AsyncTask<Object, Void, Response> {
private RestTemplate restTemplate = new RestTemplate();
private static final String SERVER_REQUEST_PATH = "/path/to/rest/service";
@Override
protected Response doInBackground(Object... args) {
String url = (String) args[0] + SERVER_REQUEST_PATH;
Request requestArgs = (Request) args[1];
Response response = null;
restTemplate.getMessageConverters().add(new MappingJackson2HttpMessageConverter());
try {
response = restTemplate.postForObject(url, requestArgs, Response.class);
} catch (RestClientException e) {
e.printStackTrace();
response = null;
}
return response;
}
}
As you can see, the code is quite simple, and is working fine most of the time but not in a particular sequence:
Then the first request after the server reboot (step 3) is not send to the server by the postForObject(...) method, but next ones are. This first request throw me an Error instead:
07-10 10:24:13.402: W/System.err(4827): org.springframework.web.client.ResourceAccessException: I/O error: null; nested exception is java.io.EOFException
07-10 10:24:13.402: W/System.err(4827): at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:491)
07-10 10:24:13.402: W/System.err(4827): at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:439)
07-10 10:24:13.402: W/System.err(4827): at org.springframework.web.client.RestTemplate.postForObject(RestTemplate.java:317)
07-10 10:24:13.402: W/System.err(4827): at com.myapp.servercommunication.RequestSender.doInBackground(RequestSender.java:42)
07-10 10:24:13.406: W/System.err(4827): at com.myapp.servercommunication.RequestSender.doInBackground(RequestSender.java:1)
07-10 10:24:13.406: W/System.err(4827): at android.os.AsyncTask$2.call(AsyncTask.java:287)
07-10 10:24:13.406: W/System.err(4827): at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305)
07-10 10:24:13.406: W/System.err(4827): at java.util.concurrent.FutureTask.run(FutureTask.java:137)
07-10 10:24:13.406: W/System.err(4827): at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:230)
07-10 10:24:13.406: W/System.err(4827): at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1076)
07-10 10:24:13.406: W/System.err(4827): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:569)
07-10 10:24:13.406: W/System.err(4827): at java.lang.Thread.run(Thread.java:856)
07-10 10:24:13.409: W/System.err(4827): Caused by: java.io.EOFException
07-10 10:24:13.413: W/System.err(4827): at libcore.io.Streams.readAsciiLine(Streams.java:203)
07-10 10:24:13.417: W/System.err(4827): at libcore.net.http.HttpEngine.readResponseHeaders(HttpEngine.java:560)
07-10 10:24:13.417: W/System.err(4827): at libcore.net.http.HttpEngine.readResponse(HttpEngine.java:813)
07-10 10:24:13.417: W/System.err(4827): at libcore.net.http.HttpURLConnectionImpl.getResponse(HttpURLConnectionImpl.java:274)
07-10 10:24:13.417: W/System.err(4827): at libcore.net.http.HttpURLConnectionImpl.getResponseCode(HttpURLConnectionImpl.java:486)
07-10 10:24:13.417: W/System.err(4827): at org.springframework.http.client.SimpleClientHttpResponse.getRawStatusCode(SimpleClientHttpResponse.java:54)
07-10 10:24:13.417: W/System.err(4827): at org.springframework.http.client.SimpleClientHttpResponse.getStatusCode(SimpleClientHttpResponse.java:80)
07-10 10:24:13.421: W/System.err(4827): at org.springframework.web.client.DefaultResponseErrorHandler.hasError(DefaultResponseErrorHandler.java:46)
07-10 10:24:13.421: W/System.err(4827): at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:477)
07-10 10:24:13.421: W/System.
err(4827): ... 11 more
Even if the use case isn't important I'm wondering why this error is thrown, is there a problem with my implementation, or is it a quite normal behavior of RestTemplate?
No doubts java.io.EOFException
appears on the server side. If you use keep-alive on your server side - switch it off like this:
HttpHeaders headers = new HttpHeaders();
headers.set("Connection", "Close");
or this: System.setProperty("http.keepAlive", "false");
Another solution is changing the http client.In Spring for Android the default HTTP Client for a RestTemplate
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
yourRestTemplate.setRequestFactory(new HttpComponentsClientHttpRequestFactory());
Please refer this:http://static.springsource.org/spring-android/docs/1.0.1.RELEASE/reference/htmlsingle/#d4e34
Spring RestTemplate
is not an ideal REST client and unfortunately there are a lot of problems with it in production code.