Исключение при использовании HttpRequest.execute (): недопустимое использование SingleClientConnManager: соединение все еще выделено - PullRequest
80 голосов
/ 06 января 2011

Я использую google-api-client-java 1.2.1-alpha для выполнения запроса POST и получаю следующую трассировку стека при выполнении () запроса HttpRequest.

Это происходит сразу после того, как я перехватил и проигнорировал ошибку 403 от предыдущего POST к тому же URL-адресу и повторно использовал транспорт для последующего запроса. (Он находится в цикле вставки нескольких записей в один канал ATOM).

Есть ли что-то, что я должен сделать, чтобы "очистить" после 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)

Почему код ниже меня пытается получить новое соединение?

Ответы [ 9 ]

80 голосов
/ 07 января 2011

Вам нужно использовать тело ответа, прежде чем вы сможете повторно использовать соединение для другого запроса.Вы должны не только прочитать состояние ответа, но и полностью прочитать ответ InputStream до последнего байта, при этом вы просто игнорируете прочитанные байты.

42 голосов
/ 18 июля 2011

Я столкнулся с аналогичной проблемой при использовании HttpClient с Jetty для создания тестовой среды Мне пришлось создать несколько запросов к сервлету от моего клиента, но при выполнении он выдавал то же исключение.

Я нашел альтернативу на http://foo.jasonhudgins.com/2010/03/http-connections-revisited.html

Вы также можете использовать этот следующий метод для создания экземпляра вашего клиента.

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;
}
9 голосов
/ 08 февраля 2013

Аналогичное сообщение об исключении (поскольку, по крайней мере, 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.

Это исключение может возникнуть, когда два или более потоков взаимодействуют с одним org.apache.http.impl.client.DefaultHttpClient.

Как сделать экземпляр 4.2 DefaultHttpClient поточно-безопасным экземпляром ( threadsafe в том смысле, что два или более потоков могут взаимодействовать с ним без получения сообщения об ошибке выше)? Предоставьте DefaultHttpClient пул соединений ClientConnectionManager в виде 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);
        }
    }
}
8 голосов
/ 10 января 2011

Это часто задаваемый вопрос. Ответ BalusC правильный. Пожалуйста, перехватите HttpReponseException и вызовите HttpResponseException. response . ignore (). Если вам нужно прочитать сообщение об ошибке, используйте ответ. parseAsString (), если вы не знаете тип содержимого ответа, иначе, если вы знаете тип содержимого, используйте ответ. parseAs (MyType.class).

Простой фрагмент кода из YouTubeSample.java в youtube-jsonc-sample (хотя обычно вы захотите сделать что-то умнее в реальном приложении):

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

Полное раскрытие: я владелец проекта google-api-java-client .

3 голосов
/ 18 октября 2012

У меня была такая же проблема с объектом jax-rs (resteasy) Response в моих модульных тестах. Я решил это с помощью звонка на response.releaseConnection(); ReleaseConnection () - метод только для объекта resteasy ClientResponse, поэтому мне пришлось добавить приведение от Response до ClientResponse.

1 голос
/ 10 июня 2014

Попробуйте это

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");
    }
0 голосов
/ 24 июня 2019

просто используйте ответ, как показано ниже, который решит проблему

response.getEntity().consumeContent();
0 голосов
/ 24 августа 2014

Считайте InputStream так:

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() + "" );
    }
}
0 голосов
/ 08 февраля 2013

Хорошо, у меня похожая проблема, все эти решения не работают, я тестировал на каком-то устройстве, проблема была в дате устройства, это был 2011 вместо 2013, проверьте также, это может помочь

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...