In my previous post, Rest client using Android-Annotations I described how easy it is to create rest clients that use Spring Android using Android-Annotations. Sometimes, requests sent with the current version of Spring Android fail with [cci]EOFException[/cci] (Spring Android Bug: INT-2837 which in turn depends on issue-116 in google-http-java-client). For me, this happened quite randomly and most of the times when I was sending some requests on opening the application after it had been put in background. Here is the stack-trace of the Exception:
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)
Although, the bug has already been addressed, it didn’t make it through yet in the official release. Until then, there are a few workarounds to go through this. It seems that it’s happening because of a combination of Keep-Alive being set and using the standard J2SE HTTP Client, which is HttpURLConnection
. There are two solutions that work:
- Switch off Keep-Alive: `System.setProperty("http.keepAlive", "false");` turns off `keepAlive` connections. But keep alive connections greatly increase performance so it is better not to disable them. If this doesn't work, keep alive connections can also be disabled like so:
HttpHeaders headers = new HttpHeaders(); headers.set("Connection", "Close"); // TODO: Set header in HttpEntity in RestTemplate
- Change the HTTP Client: In Spring for Android, 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`. As pointed earlier, the bug in Spring Android depends on a bug in `HttpURLConnection`. We can explicitly set the client to the old one like so: ```java restTemplate.setRequestFactory(new HttpComponentsClientHttpRequestFactory()); ```
Both of the above methods require you to get an access to the rest template object. With rest clients built with android annotations, you can define the following method in your annotated interface to get access to the rest template object that would be used for connections. No need to give a definition, Andorid-Annotations will do that for you.
public RestTemplate getRestTemplate();