1

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.

mnel
  • 113,303
  • 27
  • 265
  • 254
Benny
  • 242
  • 1
  • 5
  • 17
  • I guess it might also be good to ask..... why do I need to release the connection? Is that something I need to worry about with a RESTful service? – Benny Dec 06 '12 at 01:11
  • 1
    see http://stackoverflow.com/questions/12839473/httpcomponents-not-working-as-documented – Suresh Kumar Dec 06 '12 at 01:17
  • Which HttpClient version do you use? The releaseConnection method is available [since 4.2](http://hc.apache.org/httpcomponents-client-ga/httpclient/apidocs/org/apache/http/client/methods/HttpRequestBase.html#releaseConnection()) – Ervi B Dec 06 '12 at 01:29
  • I'm using 4.2.2. I added all the most recent jars to the project libraries that were outlined as required here: http://hc.apache.org/httpcomponents-client-ga/quickstart.html – Benny Dec 06 '12 at 19:25

4 Answers4

4

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();
    }
}
Taky
  • 5,284
  • 1
  • 20
  • 29
  • Effectively I had a JAR hell, that I hadn't before, related with gwt-dev.jar library being used (which uses a pre-4.2 HttpClient classes INSIDE the jar). I have a maven-tree dependency hell involved, which I spent hours last friday trying to get solved and I couldn't. I've tried your approach but no CloseableHttpResponse class found. – Chexpir Jan 13 '14 at 10:38
  • @Chexpir have you received this exception in run-time or in compile-time? – Taky Jan 15 '14 at 11:10
  • In runtime, but don't worry I got it sorted out at the end, deleting some .classpath paths related with GWT so maven can take care cleanly of all the compiling....or something like that. bounty for you as the best answer I got! thanks! – Chexpir Jan 15 '14 at 13:58
1

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.

vanOekel
  • 6,358
  • 1
  • 21
  • 56
1

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

aw

Sinto
  • 920
  • 5
  • 10
0

use httpcomponents-client-4.2.1