使用 HttpRequest.execute() 时出现异常:SingleClientConnManager 的无效使用:连接仍分配
-
26-09-2019 - |
题
我正在使用 google-api-client-java 1.2.1-alpha 执行 POST 请求,并且当我执行() HttpRequest 时得到以下堆栈跟踪。
在我捕获并忽略上一个 POST 到同一 URL 的 403 错误并重新使用后续请求的传输后,就会立即发生这种情况。(它在一个循环中将多个条目插入到同一个 ATOM feed 中)。
出现 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
到最后一个字节,其中你只是忽略了读取的字节。
其他提示
我使用的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;
}
一个类似的异常消息(因为至少阿帕奇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
相互作用。
你怎么能做出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。回复.忽略()。如果需要阅读错误消息,请使用响应。解析为字符串() 如果您不知道响应内容类型,否则如果您知道内容类型,请使用响应。解析为(MyType.class)。
一个简单的代码片段来自 YouTubeSample.java 在 youtube-jsonc-样本 (尽管通常您会希望在实际应用程序中做一些更聪明的事情):
} catch (HttpResponseException e) {
System.err.println(e.response.parseAsString());
}
全面披露:我是该公司的所有者 谷歌 API Java 客户端 项目。
我在我的单元测试用JAX-RS(RestEasy的)Response
对象相同的问题。
我解决了这个一起response.releaseConnection();
通话
所述releaseConnection() - 。方法是仅在RestEasy的ClientResponse
对象,所以我不得不从Response
添加铸造到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");
}
好吧,我有类似的问题,所有这些解决方案不工作,我的设备上进行测试,问题是日期装置,这是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();