Search code examples
restconcurrencyresteasyput

How to make batch (concurrently) PUT calls using RestEasy?


I am trying to make multiple PUT requests to a server and each of these are independent. Finally, all the response status codes are &&ed and function returns a boolean on success/failure. However, in this approach I have to wait for each response which increases the delay based on the number of put requests.

I was wondering if they can be made concurrently thus getting a latency equal to the longest call regardless of number of calls. (Assuming that the server can handle all of them at the same time). Instead of writing a own wrapper wondering if there is something RestEasy already provided.

I am using RestEasy and currently this is how I am doing it:

public boolean makePuts(Entity[] entities) {
    boolean success = true;
    for (Entity entity : entities) {
        Response response = //Make put call using RestEasy.
        success = success && putContentAccepted(response);
    }
    return success;
}

private boolean putContentAccepted(final Response response) {
        return response != null &&
           ((response.getStatus() == Response.Status.NO_CONTENT.getStatusCode()) ||
           (response.getStatus() == Response.Status.CREATED.getStatusCode()) ||
           (response.getStatus() == Response.Status.OK.getStatusCode()));
    }

PS: I have typed the function and have not compiled it, please excuse me for any syntactical mistakes. The function sheds insight on what I am doing currently.

Thanks!

Harsha P


Solution

  • I did this using async and a CountDownLatch. Let me know if there is some better way.

    final List<Future<Response>> futureList = new ArrayList<>();
    final List<> responseList = new ArrayList<Response>();
    final CountDownLatch latch = new CountDownLatch(requestModels.size());
    for (URI uri : uriList) {
        WebTarget target;
        //Use an input model object if there is need for entity, I am assuming just a list of URI. 
        //Rather take it as an object which has URI, Entity.
        futureList.add(target.request().async().put(null, new InvocationCallback<Response>() {
            @Override
            public void completed(Response response) {
                responseList.add(response);
            }
    
            @Override
            public void failed(Throwable throwable) {
                //handle error
            }
         }));
    }
    try {
        latch.await();
        return responseList;
        } catch (InterruptedException e) {
            //handle it
        }