Eccezione utilizzando HttpRequest.execute (): uso non valido di SingleClientConnManager: connessione ancora allocata

Sto usando google-api-client-java 1.2.1-alpha per eseguire una richiesta POST e sto ottenendo il seguente stacktrace quando eseguo () HttpRequest.

Accade immediatamente dopo che ho catturato e ignorato un errore 403 da un POST precedente allo stesso URL e riutilizzato il trasporto per la richiesta successiva. (È in un ciclo che inserisce più voci sullo stesso feed ATOM).

C’è qualcosa che dovrei fare per ‘ripulire’ dopo un 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) 

Perché il codice sotto di me sta cercando di acquisire una nuova connessione?

È necessario consumare il corpo della risposta prima di poter riutilizzare la connessione per un’altra richiesta. Non dovresti solo leggere lo stato della risposta, ma leggere la risposta InputStream completamente sull’ultimo byte per cui devi semplicemente ignorare i byte letti.

Stavo affrontando un problema simile quando utilizzavo HttpClient con Jetty per creare un framework di test. Ho dovuto creare più richieste al Servelet dal mio client, ma stava dando la stessa eccezione quando eseguito.

Ho trovato un’alternativa su http://foo.jasonhudgins.com/2010/03/http-connections-revisited.html

È inoltre ansible utilizzare questo metodo seguente per creare un’istanza del client.

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

Un messaggio di eccezione simile (poiché almeno Apache Jarkata Commons Client HTTP 4.2) è:

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

Questa eccezione può verificarsi quando due o più thread interagiscono con un singolo org.apache.http.impl.client.DefaultHttpClient .

Come si può creare un’istanza di DefaultHttpClient 4.2 thread-safe ( thread-safe nel senso che due o più thread possono interagire con esso senza arrivare al di sopra del messaggio di errore)? Fornire DefaultHttpClient con un ClientConnectionManager connessione-pool ClientConnectionManager nella forma di 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); } } } 

Questa è una domanda frequente. La risposta di BalusC è corretta. Prendi HttpReponseException e chiama HttpResponseException. risposta . ignora (). Se è necessario leggere il messaggio di errore, utilizzare la risposta. parseAsString () se non si conosce il tipo di contenuto della risposta, altrimenti se si conosce il tipo di contenuto utilizzare la risposta. parseAs (MyType.class).

Un semplice frammento di codice da YouTubeSample.java in youtube-jsonc-sample (anche se in genere ti consigliamo di fare qualcosa di più intelligente in un’applicazione reale):

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

Divulgazione completa: sono un proprietario del progetto google-api-java-client .

Ho avuto lo stesso problema con un object Response jax-rs (resteasy) nei miei test di unità. Ho risolto questo con una chiamata a response.releaseConnection(); Il metodo releaseConnection () – è solo sull’object ClientResponse resteasy, quindi ho dovuto aggiungere un cast da Response a ClientResponse .

Ok, ho un problema simile, tutte quelle soluzioni non funzionano, ho provato su qualche dispositivo, il problema era la data nel dispositivo, era il 2011 invece del 2013, controlla anche questo può aiutare.

Prova questo

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

Leggi l’InputStream come questo:

 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() + "" ); } }