问题
I am building a testing project using HTTPClient to test restful services. Here is the code that I am so far successfully using to get a 200 OK response on a GET. However, I am getting an error on .releaseConnection, which the HTTPClient documentation says is important to use.
Code:
public class Container {
public String tryGet() {
String getResult = null;
DefaultHttpClient httpclient = new DefaultHttpClient();
HttpGet httpGet = new HttpGet("http://test.url");
try {
HttpResponse response1 = httpclient.execute(httpGet);
System.out.println(response1.getStatusLine());
getResult = response1.getStatusLine().toString();
} catch (ClientProtocolException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
httpGet.releaseConnection();
}
return getResult;
}
}
When running my junit test, I get the following error related to .releaseConnection():
java.lang.NoSuchMethodError: org.apache.http.client.methods.HttpGet.releaseConnection()V
at com.qa.Container.tryGet(CreativeContainer.java:49)
at com.qa.SandboxTest.test(SandboxTest.java:23)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28)
at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:31)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:44)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:180)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:41)
at org.junit.runners.ParentRunner$1.evaluate(ParentRunner.java:173)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28)
at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:31)
at org.junit.runners.ParentRunner.run(ParentRunner.java:220)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
The code is ugly, I know. I'm just getting started with this.
回答1:
The method HttpRequestBase#releaseConnection() definetely was added at 4.2 version.
Probably you have jar hell. If compiler has no compilation errors another version of the class can be loaded at runtime. The real cause depends from your build tool. If you are using maven/gradle there can be some transitive dependency.
So actually HttpRequestBase#releaseConnection() method just proxy invocation to AbstractExecutionAwareRequest#reset(). And AbstractExecutionAwareRequest#reset() just cancel method execution. Probably it is not what do you need.
The correct way to execute and release httpClient resources is to close httpResponse, which means you can release Thread in httpClient's internal threadPool.
private static String makeRequest(HttpUriRequest httpRequest) throws IOException {
CloseableHttpResponse httpResponse = httpClient.execute(httpRequest);
try {
HttpEntity httpEntity = httpResponse.getEntity();
StringWriter writer = new StringWriter();
IOUtils.copy(httpEntity.getContent(), writer, "UTF-8");
return writer.toString();
} finally {
httpResponse.close();
}
}
回答2:
The quickstart is not really clear on all the jars you need to use httpclient 4.2.2. I created a Maven project with dependency org.apache.httpcomponents:httpclient:4.2.2 and got the following additional jars:
- org.apache.httpcomponents:httpcore:4.2.2
- commons-logging:commons-logging:1.1.1
- commons-codec:commons-codec:1.6
I copied your code (changed the HttpGet-url to "https://www.google.com/") and ran a JUnit test with it, there were no errors.
The ".releaseConnection()" is indeed required to ensure connections are closed (after something has gone wrong). Omitting ".releaseConnection()" could result in open connections doing nothing on your system.
Since you are still in a development start-phase, I would advice to use the last HttpClient 4.3.x version (currenlty 4.3.1). The 4.3 version contains some good improvements over the 4.2 version, but also usage has changed. E.g. in the quickstart you'll see that ".releaseConnection()" is no longer used (it is deprecated), instead the response object is closed to ensure connections are closed.
回答3:
This method was introduced since version 4.2 see javadoc
So you need to use versions > 4.2 I tested it with version 4.3.1 and is working fine.
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.3.1</version>
</dependency>
http://mvnrepository.com/artifact/org.apache.httpcomponents/httpclient/4.3.1
回答4:
use httpcomponents-client-4.2.1
来源:https://stackoverflow.com/questions/13735367/httpclient-nosuchmethoderror-for-releaseconnection