Исключение с использованием HttpRequest.execute(): недопустимое использование SingleClientConnManager: соединение все еще выделено

Я использую 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)

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

Ответ 1

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

Ответ 2

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

Я нашел альтернативу в 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;
}

Ответ 3

Аналогичное сообщение об исключении (поскольку, по крайней мере, 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 (потокобезопасное в том смысле, что два или более потока могут взаимодействовать с ним без получения сообщения об ошибке)? Предоставьте 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);
        }
    }
}

Ответ 4

Это часто задаваемый вопрос. Реакция 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.

Ответ 5

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

Ответ 6

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

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

Ответ 7

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

Ответ 8

Прочитайте 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() + "" );
    }
}

Ответ 9

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

response.getEntity().consumeContent();