I have a loop over a bunch of URLs, for each one I'm doing the following:
private String doQuery(String url) { HttpGet httpGet = new HttpGet(url); setDefaultHeaders(httpGet); // static method HttpResponse response = httpClient.execute(httpGet); // httpClient instantiated in constructor int rc = response.getStatusLine().getStatusCode(); if (rc != 200) { // some stuff... return; } HttpEntity entity = response.getEntity(); if (entity == null) { // some stuff... return; } // process the entity, get input stream etc }
The first query is fine, the second throws this exception:
Exception in thread "main" java.lang.IllegalStateException: Invalid use of SingleClientConnManager: connection still allocated. Make sure to release the connection before allocating another one. at org.apache.http.impl.conn.SingleClientConnManager.getConnection(SingleClientConnManager.java:199) at org.apache.http.impl.conn.SingleClientConnManager$1.getConnection(SingleClientConnManager.java:173)......
This is just a simple single-threaded app. How can I release this connection?
You do not need to explicitly close the HttpClient, however, (you may be doing this already but worth noting) you should ensure that connections are released after method execution. Edit: The ClientConnectionManager within the HttpClient is going to be responsible for maintaining the state of connections.
CloseableHttpClient is the base class of the httpclient library, the one all implementations use. Other subclasses are for the most part deprecated. The HttpClient is an interface for this class and other classes. You should then use the CloseableHttpClient in your code, and create it using the HttpClientBuilder .
HttpClient tries to mitigate the problem by testing whether the connection is 'stale', that is no longer valid because it was closed on the server side, prior to using the connection for executing an HTTP request. The stale connection check is not 100% reliable.
The recommended way, by Httpcomponents 4.1, is to close connection and release any underlying resources:
EntityUtils.consume(HttpEntity)
where HttpEntity
passed is a response entity.
This seems to work great :
if( response.getEntity() != null ) { response.getEntity().consumeContent(); }//if
And don't forget to consume the entity even if you didn't open its content. For instance, you expect a HTTP_OK status from the response and don't get it, you still have to consume the entity !
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With