Exceção usando HttpRequest.execute (): uso inválido de SingleClientConnManager: conexão ainda alocada

Estou usando o google-api-client-java 1.2.1-alpha para executar uma solicitação POST e estou recebendo o seguinte stacktrace quando executo () o HttpRequest.

Isso acontece imediatamente depois de eu capturar e ignorar um erro 403 de um POST anterior para a mesma URL e reutilizar o transporte para a solicitação subsequente. (Está em um loop inserindo várias inputs no mesmo feed ATOM).

Há algo que eu deveria estar fazendo para ‘limpar’ depois de um 403?

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) at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:390) at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:641) at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:576) at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:554) at com.google.api.client.apache.ApacheHttpRequest.execute(ApacheHttpRequest.java:47) at com.google.api.client.http.HttpRequest.execute(HttpRequest.java:207) at au.com.machaira.pss.gape.RedirectHandler.execute(RedirectHandler.java:38) at au.com.machaira.pss.gape.ss.model.records.TableEntry.executeModification(TableEntry.java:81) 

Por que o código abaixo de mim estaria tentando adquirir uma nova conexão?

Você precisa consumir o corpo da resposta antes de poder reutilizar a conexão para outra solicitação. Você deve não apenas ler o status da resposta, mas ler a resposta InputStream até o último byte, ignorando os bytes lidos.

Eu estava enfrentando um problema semelhante ao usar o HttpClient com Jetty para criar uma estrutura de teste. Eu tive que criar vários pedidos para o Servelet do meu cliente, mas estava dando a mesma exceção quando executado.

Eu encontrei uma alternativa em http://foo.jasonhudgins.com/2010/03/http-connections-revisited.html

Você também pode usar este método a seguir para instanciar seu cliente.

 public static DefaultHttpClient getThreadSafeClient() { DefaultHttpClient client = new DefaultHttpClient(); ClientConnectionManager mgr = client.getConnectionManager(); HttpParams params = client.getParams(); client = new DefaultHttpClient(new ThreadSafeClientConnManager(params, mgr.getSchemeRegistry()), params); return client; } 

Uma mensagem de exceção similar (desde pelo menos o Apache Jarkata Commons HTTP Client 4.2) é:

java.lang.IllegalStateException: Invalid use of BasicClientConnManager: connection still allocated. Make sure to release the connection before allocating another one.

Essa exceção pode acontecer quando dois ou mais segmentos interagem com um único org.apache.http.impl.client.DefaultHttpClient .

Como você pode tornar uma instância 4.2 DefaultHttpClient threadsafe ( threadsafe no sentido de que dois ou mais threads podem interagir com ela sem ficar acima da mensagem de erro)? Forneça o DefaultHttpClient com um ClientConnectionManager pool de conexões na forma de org.apache.http.impl.conn.PoolingClientConnectionManager !

 /* using  org.apache.httpcomponents httpclient 4.2.2  */ import org.apache.http.HttpResponse; import org.apache.http.HttpStatus; import org.apache.http.params.HttpConnectionParams; import org.apache.http.client.HttpClient; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.impl.conn.PoolingClientConnectionManager; import org.apache.http.impl.conn.SchemeRegistryFactory; import org.apache.http.params.HttpParams; import org.apache.http.client.methods.HttpGet; public class MyComponent { private HttpClient client; { PoolingClientConnectionManager conMan = new PoolingClientConnectionManager( SchemeRegistryFactory.createDefault() ); conMan.setMaxTotal(200); conMan.setDefaultMaxPerRoute(200); client = new DefaultHttpClient(conMan); //The following parameter configurations are not //neccessary for this example, but they show how //to further tweak the HttpClient HttpParams params = client.getParams(); HttpConnectionParams.setConnectionTimeout(params, 20000); HttpConnectionParams.setSoTimeout(params, 15000); } //This method can be called concurrently by several threads private InputStream getResource(String uri) { try { HttpGet method = new HttpGet(uri); HttpResponse httpResponse = client.execute(method); int statusCode = httpResponse.getStatusLine().getStatusCode(); InputStream is = null; if (HttpStatus.SC_OK == statusCode) { logger.debug("200 OK Amazon request"); is = httpResponse.getEntity().getContent(); } else { logger.debug("Something went wrong, statusCode is {}", statusCode); EntityUtils.consume(httpResponse.getEntity()); } return is; } catch (Exception e) { logger.error("Something went terribly wrong", e); throw new RuntimeException(e); } } } 

Esta é uma pergunta frequente. A resposta da BalusC está correta. Por favor, pegar HttpReponseException e chamar HttpResponseException. resposta . ignore (). Se você precisar ler a mensagem de erro, use response. parseAsString () se você não souber o tipo de conteúdo da resposta, senão se você souber o tipo de conteúdo use response. parseAs (MyType.class).

Um snippet de código simples do YouTubeSample.java no youtube-jsonc-sample (embora geralmente você queira fazer algo mais inteligente em um aplicativo real):

  } catch (HttpResponseException e) { System.err.println(e.response.parseAsString()); } 

Divulgação completa: sou proprietário do projeto google-api-java-client .

Eu tive o mesmo problema com um object de Response jax-rs (resteasy) em meus testes de unidade. Eu resolvi isso com uma chamada para response.releaseConnection(); O método releaseConnection () – é apenas no object ClientResponse , então tive que adicionar uma conversão de Response ao ClientResponse .

Ok, eu tenho problema semelhante, toda essa solução não funciona, testei em algum dispositivo, problema era data no dispositivo, era 2011 ao invés de 2013, cheque também isso pode ajudar.

Tente isso

 HttpResponse response = Client.execute(httpGet); response.getEntity().consumeContent(); StatusLine statusLine = response.getStatusLine(); int statusCode = statusLine.getStatusCode(); if (statusCode == 200) { //task Log.i("Connection", "OK"); }else{ Log.i("Connection", "Down"); } 

Leia o InputStream assim:

 if( response.getStatusLine().getStatusCode() == 200 ) { HttpEntity entity = response.getEntity(); InputStream content = entity.getContent(); try { sb = new StringBuilder(); BufferedReader bufferedReader = new BufferedReader( new InputStreamReader( content ), 8 ); String line; while( ( line = bufferedReader.readLine() ) != null ) { sb.append( line ); } bufferedReader.close(); content.close(); } catch( Exception ex ) { Log.e( "statusCode", ex.getMessage() + "" ); } } 
    Intereting Posts