Estoy usando google-api-client-java 1.2.1-alpha para ejecutar una solicitud POST, y obtengo el siguiente seguimiento de pila cuando ejecuto () HttpRequest.
Ocurre inmediatamente después de detectar e ignorar un error 403 de un POST anterior a la misma URL y reutilizar el transporte para la solicitud posterior. (Está en un bucle que inserta varias entradas en la misma alimentación ATOM).
¿Hay algo que deba hacer para 'limpiar' después de 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)
¿Por qué el código debajo de mí intentaría adquirir una nueva conexión?
java
httpclient
google-api-java-client
David Bullock
fuente
fuente
Respuestas:
Debe consumir el cuerpo de la respuesta antes de poder reutilizar la conexión para otra solicitud. No solo debe leer el estado de la respuesta, sino leer la respuesta por
InputStream
completo hasta el último byte, por lo que simplemente ignora los bytes leídos.fuente
google-api-java-client
, esto significaba atrapar elIOException
arrojadoHttpResponse.execute()
, probarlo / transmitirloHttpResponseException
, acceder alresponse
miembro y luego invocarloparaseAsString()
. (Que resultó ser información útil de todos modos: -)HttpRequest.execute()
limpiará automáticamente estos recursos si el método no devuelve unHttpResponse
objeto. Además, JavaDoc deHttpResponse
ahora recomienda llamarresponse.disconnect()
en caso de no leer completamente el contenido de la respuesta HTTP (en unfinally
bloque).Me enfrentaba a un problema similar al usar HttpClient con Jetty para crear un marco de prueba. Tuve que crear múltiples solicitudes al Servelet desde mi cliente, pero estaba dando la misma excepción cuando se ejecutó.
Encontré una alternativa en http://foo.jasonhudgins.com/2010/03/http-connections-revisited.html
También puede utilizar este método siguiente para crear una instancia de su 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; }
fuente
Un mensaje de excepción similar (ya que al menos Apache Jarkata Commons HTTP Client 4.2) es:
java.lang.IllegalStateException: Invalid use of BasicClientConnManager: connection still allocated. Make sure to release the connection before allocating another one.
Esta excepción puede ocurrir cuando dos o más subprocesos interactúan con uno
org.apache.http.impl.client.DefaultHttpClient
.¿Cómo puede hacer que una
DefaultHttpClient
instancia 4.2 sea segura para subprocesos ( segura para subprocesos en el sentido de que dos o más subprocesos pueden interactuar con ella sin obtener el mensaje de error anterior)? ProporcionarDefaultHttpClient
un pool de conexionesClientConnectionManager
en forma deorg.apache.http.impl.conn.PoolingClientConnectionManager
!/* using <dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId> <version>4.2.2</version> </dependency> */ 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); } } }
fuente
Ésta es una pregunta frecuente. La respuesta de BalusC es correcta. Por favor, coger HttpReponseException , y llamar a HttpResponseException. respuesta . ignorar (). Si necesita leer el mensaje de error, use response. parseAsString () si no conoce el tipo de contenido de la respuesta, de lo contrario, si conoce el tipo de contenido, use la respuesta. parseAs (MyType.class).
Un simple fragmento de código de YouTubeSample.java en youtube-jsonc-sample (aunque normalmente querrás hacer algo más inteligente en una aplicación real):
} catch (HttpResponseException e) { System.err.println(e.response.parseAsString()); }
Divulgación completa: soy propietario del proyecto google-api-java-client .
fuente
Tuve el mismo problema con un
Response
objeto jax-rs (resteasy) en mis pruebas unitarias.response.releaseConnection();
Resolví esto con una llamada a The releaseConnection () - El método está solo en elClientResponse
objeto resteasy , así que tuve que agregar un elenco deResponse
aClientResponse
.fuente
Prueba esto
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"); }
fuente
Ok, tengo un problema similar, todas esas soluciones no funcionan, probé en algún dispositivo, el problema fue la fecha en el dispositivo, fue 2011 en lugar de 2013, verifique también que esto puede ayudar.
fuente
Lea InputStream así:
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() + "" ); } }
fuente
solo consume la respuesta como a continuación, eso resolverá el problema
fuente