Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

REST Java client API: Release connection before allocating another

Tags:

java

rest

jax-rs

I'm calling a REST service using this test code:

public class TestRESTServices {
    private static final String BASE_URL = "http://localhost/ma.ge.persistence-1.0/rest/reference";
    private static URI uri = UriBuilder.fromUri(BASE_URL).port(8080).build();
    private static Client client = ClientBuilder.newClient();

    @Test
    public void createAndDeleteAReference() {

        Reference r = ReferenceFactory.createReference("Maz",
                "dummy", 1.7);
        Response response = client.target(uri).request().post(Entity.entity(r, MediaType.APPLICATION_JSON));
        assertEquals(Response.Status.CREATED, response.getStatusInfo());

        URI referenceURI = response.getLocation();

        // Get the posted reference
        response = client.target(referenceURI).request().get();

        Reference retreivedRef = response.readEntity(Reference.class);
        assertEquals(Response.Status.OK, response.getStatusInfo());
        assertEquals(retreivedRef.getName(), r.getName());

    }

But I get the following error:

javax.ws.rs.ProcessingException: Unable to invoke request at org.jboss.resteasy.client.jaxrs.engines.ApacheHttpClient4Engine.invoke(ApacheHttpClient4Engine.java:287) at org.jboss.resteasy.client.jaxrs.internal.ClientInvocation.invoke(ClientInvocation.java:407) at org.jboss.resteasy.client.jaxrs.internal.ClientInvocationBuilder.get(ClientInvocationBuilder.java:159) at ma.gesto.persistence.TestRESTServices.createAndDeleteAReference(TestRESTServices.java:34) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:606) at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47) at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44) at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17) at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50) at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238) at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63) at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236) at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53) at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229) at org.junit.runners.ParentRunner.run(ParentRunner.java:309) 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:459) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192) Caused by: java.lang.IllegalStateException: Invalid use of BasicClientConnManager: connection still allocated. Make sure to release the connection before allocating another one. at org.apache.http.impl.conn.BasicClientConnectionManager.getConnection(BasicClientConnectionManager.java:162) at org.apache.http.impl.conn.BasicClientConnectionManager$1.getConnection(BasicClientConnectionManager.java:139) at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:456) at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:906) at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:805) at org.jboss.resteasy.client.jaxrs.engines.ApacheHttpClient4Engine.invoke(ApacheHttpClient4Engine.java:283) ... 26 more

like image 452
ElArbi Avatar asked Mar 18 '23 05:03

ElArbi


1 Answers

The Client interface represents external resources. As such, it is a critical mistake to create and store one in a static variable. This is wrong:

private static Client client = ClientBuilder.newClient();

This is ok for unit testing:

private Client client;

@Before
public void setUp() {
    this.client = ClientBuilder.newClient();
}

@After
public void tearDown() {
    this.client.close();
}

In normal code you would want to wrap Client usage in a try-with-resources or try..finally:

Client client = ClientBuilder.newClient();
try {
    // use the client to make requests
} finally {
    client.close();
}

Ideally there would be a way to manage a pool of Client instances for reuse.

like image 70
gknicker Avatar answered Apr 06 '23 03:04

gknicker