2

I am trying to reuse a Jersey2(Jersey 2.16) Client for async invocation. However after 2 requests, I see that the threads going into a waiting state, waiting on a lock. Since client creation is an expensive operation, I am trying to reuse the client in the async calls. The issue occurs only with ApacheConnectorProvider as the connector class. I want to use ApacheConnectorProvider, as I need to use a proxy and set SSL properties and I want to use PoolingHttpClientConnectionManager.

The sample code is given below:

public class Example {
    Integer eventId = 0;

    private ClientConfig getClientConfig() 
    {
        ClientConfig clientConfig = new ClientConfig();
        ApacheConnectorProvider provider = new ApacheConnectorProvider();
        clientConfig.property(ClientProperties.REQUEST_ENTITY_PROCESSING,RequestEntityProcessing.BUFFERED);
        clientConfig.connectorProvider(provider);
        return clientConfig;
    }

    private Client createClient()  
    {   
        Client client = ClientBuilder.newClient(getClientConfig());
        return client;
    }

    public void testAsyncCall()  
    {
        Client client = createClient();
        System.out.println("Testing a new Async call on thread " + Thread.currentThread().getId());

        JSONObject jsonObject    = new JSONObject();
        jsonObject.put("value", eventId++);

        invoker(client, "http://requestb.in/nn0sffnn" , jsonObject);
        invoker(client, "http://requestb.in/nn0sffnn" , jsonObject);
        invoker(client, "http://requestb.in/nn0sffnn" , jsonObject);
        client.close();
    }

    private void invoker(Client client, String URI, JSONObject jsonObject)
    {
        final Future<Response> responseFuture = client.target(URI)                
            .request()
            .async()
            .post(Entity.entity(jsonObject.toJSONString(), MediaType.TEXT_PLAIN));

        try {
            Response r = responseFuture.get();
            System.out.println("Response is on URI  " + URI +  " : " + r.getStatus());
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (ExecutionException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    public static void main(String args[]) 
    {
        Example client1 = new Example();
        client1.testAsyncCall();
        return;
    }
}

The response I see is:

Testing a new Async call on thread 1
Response is on URI http://requestb.in/nn0sffnn : 200
Response is on URI http://requestb.in/nn0sffnn : 200

On looking at the thread stack, I see the following trace:

"jersey-client-async-executor-0" prio=6 tid=0x043a4c00 nid=0x56f0 waiting on condition [0x03e5f000] java.lang.Thread.State: WAITING (parking) at sun.misc.Unsafe.park(Native Method) - parking to wait for <0x238ee148> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject) at java.util.concurrent.locks.LockSupport.park(LockSupport.java:186) at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2043) at org.apache.http.pool.PoolEntryFuture.await(PoolEntryFuture.java:133) at org.apache.http.pool.AbstractConnPool.getPoolEntryBlocking(AbstractConnPool.java:282) at org.apache.http.pool.AbstractConnPool.access$000(AbstractConnPool.java:64) at org.apache.http.pool.AbstractConnPool$2.getPoolEntry(AbstractConnPool.java:177) at org.apache.http.pool.AbstractConnPool$2.getPoolEntry(AbstractConnPool.java:170)

Can someone give me a suggestion as to how to reuse Client objects for async requests and may be how to get over this issue as well.

Rodrigo Taboada
  • 2,727
  • 4
  • 24
  • 27

0 Answers0