82 votes

Exception à l’aide de HttpRequest.execute() : utilisation non valide de SingleClientConnManager : connexion toujours allouée

Je suis en utilisant google-api-client-java 1.2.1-alpha pour exécuter une requête POST, et je suis de mieux en le suivant stacktrace quand j'execute() HttpRequest.

Il se produit immédiatement après que je les attraper et de les ignorer une erreur 403 partir d'un POST précédent vers la même URL, et ré-utilisé le transport de la demande ultérieure. (Il est dans une boucle de l'insertion de plusieurs entrées pour le même flux ATOM).

Il ya quelque chose que je devrais faire pour "nettoyer" après une 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 le code ci-dessous m'être d'essayer d'acquérir une nouvelle connexion?

83voto

BalusC Points 498232

Vous avez besoin de consommer le corps de la réponse avant que vous pouvez réutiliser la connexion pour une autre demande. Vous ne devriez pas seulement lire le statut de la réponse, mais lire la réponse `` entièrement pour le dernier octet par lequel vous ignorer les octets lus.

42voto

Ujjwal Wadhawan Points 552

J'ai été confronté à un problème similaire lors de l'utilisation de la HttpClient avec ponton pour construire une structure de test. J'ai dû créer de multiples demandes de la Servelet de mon client, mais Il a été de donner la même exception lors de l'exécution.

J'ai trouvé une alternative à http://foo.jasonhudgins.com/2010/03/http-connections-revisited.html

Vous pouvez également utiliser cette méthode 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;
}

9voto

Abdull Points 1666

Une exception similaire message (depuis au moins Apache Jarkata Communes 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 interagir avec un seul org.apache.http.impl.client.DefaultHttpClient.

Comment pouvez-vous faire un 4.2 DefaultHttpClient exemple des threads (thread-safe dans le sens où deux ou plusieurs threads peuvent interagir avec elle, sans obtenir au-dessus de message d'erreur)? Fournir de l' DefaultHttpClient avec une connexion de mise en commun des ClientConnectionManager sous la 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);
        }
    }
}

8voto

Yaniv Inbar Points 1331

C'est une question souvent posée. BalusC la réponse est correcte. Veuillez attraper HttpReponseException, et d'appeler HttpResponseException.réponse.ignorer(). Si vous avez besoin de lire le message d'erreur, utiliser la réponse.parseAsString() si vous ne connaissez pas le contenu de la réponse, sinon, si vous connaissez le type de contenu utiliser la réponse.parseAs(MyType.class).

Un simple extrait de code de YouTubeSample.java dans 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 un propriétaire de la google-api-java-client du projet.

3voto

markus Points 378

J’ai eu le même problème avec un jax-rs (resteasy) objet dans mes tests unitaires. J’ai résolu ce problème avec un appel à la releaseConnection ()-méthode est seulement sur le resteasy d’objet, donc j’ai dû ajouter un cast de à `` .

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X