Development Tip

HttpRequest.execute () 사용 예외 : SingleClientConnManager의 잘못된 사용 : 연결이 여전히 할당 됨

yourdevel 2020. 10. 7. 21:18
반응형

HttpRequest.execute () 사용 예외 : SingleClientConnManager의 잘못된 사용 : 연결이 여전히 할당 됨


google-api-client-java 1.2.1-alpha를 사용하여 POST 요청을 실행하고 HttpRequest를 execute () 할 때 다음 스택 추적을 얻습니다.

이전 POST에서 동일한 URL 로의 403 오류를 포착하고 무시하고 후속 요청에 대해 전송을 다시 사용한 직후에 발생합니다. (동일한 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)

아래 코드가 연결 을 얻으려고하는 이유는 무엇 입니까?


다른 요청에 연결을 재사용하려면 먼저 응답 본문을 사용해야합니다. 응답 상태를 읽을뿐만 아니라 읽은 InputStream바이트를 무시하는 마지막 바이트까지 응답을 완전히 읽어야합니다.


Jetty와 함께 HttpClient를 사용하여 테스트 프레임 워크를 구축 할 때 비슷한 문제가 발생했습니다. 클라이언트에서 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;
}

유사한 예외 메시지 (최소한 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);
        }
    }
}

이것은 자주 묻는 질문입니다. BalusC의 응답이 정확합니다. HttpReponseException을 포착 하고 HttpResponseException을 호출하십시오. 응답 . 무시 (). 오류 메시지를 읽어야하는 경우 응답을 사용하십시오. 응답 내용 유형을 모르는 경우 parseAsString (), 그렇지 않으면 내용 유형을 알고있는 경우 응답을 사용합니다. parseAs (MyType.class).

A simple code snippet from YouTubeSample.java in youtube-jsonc-sample (though usually you'll want to do something smarter in a real application):

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

Full disclosure: I am an owner of the google-api-java-client project.


I had the same issue with a jax-rs (resteasy) Response object in my unit tests. I solved this with a call to response.releaseConnection(); The releaseConnection()-Method is only on the resteasy ClientResponse object, so I had to add a cast from Response to ClientResponse.


Try this

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, i have similar problem, all those solution not work, i tested on some device, problem was date in device, it was 2011 instead 2013, check also this can help.


Read the InputStream like this:

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

just consume the response like below, that will solve the issue

response.getEntity().consumeContent();

참고URL : https://stackoverflow.com/questions/4612573/exception-using-httprequest-execute-invalid-use-of-singleclientconnmanager-c

반응형