Exception utilisant HttpRequest.execute (): Utilisation non valide de SingleClientConnManager: connexion toujours alloué
-
26-09-2019 - |
Question
J'utilise google-api-client-java-1.2.1 alpha pour exécuter une requête POST, et je obtenir la stacktrace suivante quand j'execute () le HttpRequest.
Il arrive immédiatement après que je surprends et ignorer une erreur 403 d'un précédent à la même URL et RÉUTILISÉS le transport pour la demande ultérieure. (Il est dans une boucle d'insérer plusieurs entrées pour le même flux ATOM).
Y at-il quelque chose que je devrais faire pour « nettoyer » après 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)
Pourquoi est-ce le code ci-dessous me essayer d'acquérir une nouvelle connexion
La solution
Vous devez consommer le corps de la réponse avant de pouvoir réutiliser la connexion à une autre demande. Vous devez non seulement lire l'état de réponse, mais lisez la InputStream
de réponse pleinement au dernier octet par lequel vous ignorez les octets de lecture.
Autres conseils
Je faisais face à un problème similaire lors de l'utilisation du HttpClient avec la jetée pour construire un cadre de test. Je devais créer plusieurs demandes au Servelet de mon client, mais il fournissais la même exception lors de l'exécution.
J'ai trouvé une alternative à la http://foo.jasonhudgins.com /2010/03/http-connections-revisited.html
Vous pouvez également utiliser cette méthode suivante pour instancier votre 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 message d'exception similaire (depuis au moins Apache Commons Jarkata Client HTTP 4.2) est:
java.lang.IllegalStateException: Invalid use of BasicClientConnManager: connection still allocated.
Make sure to release the connection before allocating another one.
Cette exception peut se produire lorsque deux ou plusieurs threads interagissent avec un seul org.apache.http.impl.client.DefaultHttpClient
.
Comment pouvez-vous faire un exemple 4,2 DefaultHttpClient
threadsafe ( threadsafe dans le sens où deux ou plusieurs threads peuvent interagir avec elle sans obtenir au-dessus de message d'erreur)? Fournir DefaultHttpClient
avec une ClientConnectionManager
mise en commun connexion sous forme de org.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);
}
}
}
Cette question est souvent posée. La réponse de BalusC est correcte. S'il vous plaît prendre HttpReponseException et appeler HttpResponseException. réponse . ignorer (). Si vous avez besoin de lire le message d'erreur, utilisez la réponse. parseAsString (), d'autre si vous connaissez la réponse type de contenu d'utilisation. de parseAs (MyType.class).
Un simple extrait de code YouTubeSample.java youtube-jsonc-échantillon (bien que généralement vous aurez envie de faire quelque chose de plus intelligent dans une application réelle):
} catch (HttpResponseException e) {
System.err.println(e.response.parseAsString());
}
La divulgation complète: Je suis propriétaire du google-api-java- projet client .
J'ai eu le même problème avec un JAX-RS (resteasy) objet Response
dans mes tests unitaires.
Je résolu ce problème avec un appel à response.releaseConnection();
Le releaseConnection () -. La méthode est uniquement sur l'objet de ClientResponse
resteasy, donc je devais ajouter un casting de Response
à ClientResponse
Essayer cette
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");
}
Ok, j'ai le même problème, tous ceux qui solution ne travaille, je l'ai testé sur un périphérique, problème était la date dans l'appareil, il a été à la place 2011 2013, vérifiez également que cela peut aider.
Lire la InputStream comme ceci:
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() + "" );
}
}
consommer juste la réponse comme ci-dessous, qui résoudra le problème
response.getEntity().consumeContent();