HttpRequest.execute() を使用した場合の例外:SingleClientConnManager の無効な使用:接続はまだ割り当てられています
-
26-09-2019 - |
質問
google-api-client-java 1.2.1-alpha を使用して POST リクエストを実行しており、HttpRequest を実行すると次のスタックトレースが得られます。
この問題は、同じ URL への以前の POST からの 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
を読んではいけません。
他のヒント
私は同様の問題に直面していました。私は私のクライアントから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;
}
(少なくともアパッチJarkataコモンズHTTPクライアント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
と対話する2つの以上のスレッドを発生する可能性があります。
どのように(2つの以上のスレッドがエラーメッセージの上に取得せずにそれと対話することができるという意味で、のスレッドセーフの)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 の応答は正しいです。捕まえてください HttpResponseException, 、HttpResponseExceptionを呼び出します。応答.無視する()。エラー メッセージを読む必要がある場合は、response を使用します。文字列として解析応答のコンテンツ タイプがわからない場合は () を使用し、コンテンツ タイプがわかっている場合は応答を使用します。として解析する(MyType.class)。
以下の簡単なコード スニペット YouTubeサンプル.java で youtube-jsonc-サンプル (ただし、通常は実際のアプリケーションではもっと賢いことをしたいと思うでしょう):
} catch (HttpResponseException e) {
System.err.println(e.response.parseAsString());
}
完全な開示:私はの所有者です google-api-java-クライアント プロジェクト。
私は自分のユニットテストではJAX-RS(RESTEasyの)Response
オブジェクトと同じ問題がありました。
私はresponse.releaseConnection();
への呼び出しでこれを解決しました
releaseConnection() - 。私はClientResponse
からResponse
にキャストを追加する必要がありましたので、方法は、唯一のRESTEasy ClientResponse
オブジェクト上にある
これを試してみてください
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]を、私は同様の問題を持っている、すべてのそれらの解決策ではない仕事は、私はいくつかのデバイス上でテストされ、それはまた、この缶の助けを確認し、2011の代わりに2013でした。
このように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() + "" );
}
}
だけ
問題を解決することを、以下のような応答を消費response.getEntity().consumeContent();