Performing requests

edit

Once the RestClient has been created, requests can be sent by calling either performRequest or performRequestAsync. performRequest is synchronous and will block the calling thread and return the Response when the request is successful or throw an exception if it fails. performRequestAsync is asynchronous and accepts a ResponseListener argument that it calls with a Response when the request is successful or with an Exception if it fails.

This is synchronous:

Request request = new Request(
    "GET",  
    "/");   
Response response = restClient.performRequest(request);

The HTTP method (GET, POST, HEAD, etc)

The endpoint on the server

And this is asynchronous:

Request request = new Request(
    "GET",  
    "/");   
restClient.performRequestAsync(request, new ResponseListener() {
    @Override
    public void onSuccess(Response response) {
        
    }

    @Override
    public void onFailure(Exception exception) {
        
    }
});

The HTTP method (GET, POST, HEAD, etc)

The endpoint on the server

Handle the response

Handle the failure

You can add request parameters to the request object:

request.addParameter("pretty", "true");

You can set the body of the request to any HttpEntity:

request.setEntity(new NStringEntity(
        "{\"json\":\"text\"}",
        ContentType.APPLICATION_JSON));

The ContentType specified for the HttpEntity is important because it will be used to set the Content-Type header so that Elasticsearch can properly parse the content.

You can also set it to a String which will default to a ContentType of application/json.

request.setJsonEntity("{\"json\":\"text\"}");

RequestOptions

edit

The RequestOptions class holds parts of the request that should be shared between many requests in the same application. You can make a singleton instance and share it between all requests:

private static final RequestOptions COMMON_OPTIONS;
static {
    RequestOptions.Builder builder = RequestOptions.DEFAULT.toBuilder();
    builder.addHeader("Authorization", "Bearer " + TOKEN); 
    builder.setHttpAsyncResponseConsumerFactory(           
        new HeapBufferedResponseConsumerFactory(30 * 1024 * 1024 * 1024));
    COMMON_OPTIONS = builder.build();
}

Add any headers needed by all requests.

Customize the response consumer.

addHeader is for headers that are required for authorization or to work with a proxy in front of Elasticsearch. There is no need to set the Content-Type header because the client will automatically set that from the HttpEntity attached to the request.

You can set the NodeSelector which controls which nodes will receive requests. NodeSelector.NOT_MASTER_ONLY is a good choice.

You can also customize the response consumer used to buffer the asynchronous responses. The default consumer will buffer up to 100MB of response on the JVM heap. If the response is larger then the request will fail. You could, for example, lower the maximum size which might be useful if you are running in a heap constrained environment like the exmaple above.

Once you’ve created the singleton you can use it when making requests:

request.setOptions(COMMON_OPTIONS);

You can also customize these options on a per request basis. For example, this adds an extra header:

RequestOptions.Builder options = COMMON_OPTIONS.toBuilder();
options.addHeader("cats", "knock things off of other things");
request.setOptions(options);

Multiple parallel asynchronous actions

edit

The client is quite happy to execute many actions in parallel. The following example indexes many documents in parallel. In a real world scenario you’d probably want to use the _bulk API instead, but the example is illustative.

final CountDownLatch latch = new CountDownLatch(documents.length);
for (int i = 0; i < documents.length; i++) {
    Request request = new Request("PUT", "/posts/doc/" + i);
    //let's assume that the documents are stored in an HttpEntity array
    request.setEntity(documents[i]);
    restClient.performRequestAsync(
            request,
            new ResponseListener() {
                @Override
                public void onSuccess(Response response) {
                    
                    latch.countDown();
                }

                @Override
                public void onFailure(Exception exception) {
                    
                    latch.countDown();
                }
            }
    );
}
latch.await();

Process the returned response

Handle the returned exception, due to communication error or a response with status code that indicates an error