How to Instantiate OpenSearch Client in Java

Here we will learn how to create OpenSearch client using Java SDK. We will see how to connect to an OpenSearch cluster from a Java application for both AWS & non-AWS environments.

OpenSearchClient for non-AWS environment:

For a Gradle project, we need to add below dependencies in build.gradle file.

    api 'org.opensearch.client:opensearch-java:2.1.0'
    implementation 'org.opensearch.client:opensearch-rest-client:2.3.0'

For maven project, we would need to add them in pom.xml file.

Here is the Java code to create an instance of OpenSearchClient.

import org.apache.http.HttpHost;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.opensearch.client.RestClient;
import org.opensearch.client.json.jackson.JacksonJsonpMapper;
import org.opensearch.client.opensearch.OpenSearchClient;
import org.opensearch.client.transport.rest_client.RestClientTransport;

public class OpenSearchClientFactory {

	private static OpenSearchClient openSearchClient;

	static {
		openSearchClient = createNonAWSOpenSearchClientInstance();
	}

	private static OpenSearchClient createNonAWSOpenSearchClientInstance() {
		CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
		credentialsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials("admin", "admin"));
		RestClient restClient = RestClient.builder(new HttpHost("localhost", -1, "http"))
				.setHttpClientConfigCallback(
						httpClientBuilder -> httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider))
				.build();
		RestClientTransport restClientTransport = new RestClientTransport(restClient, new JacksonJsonpMapper());
		return new OpenSearchClient(restClientTransport);
	}

	public static OpenSearchClient getInstance() {
		return openSearchClient;
	}

}

We are using basic username/password credentials to connect to the OpenSearch endpoint here. If you don’t have any authentication for your OpenSearch cluster, you can very well remove the CredentialsProvider part. Client creation would look like below.

RestClient restClient = RestClient.builder(new HttpHost("localhost", -1, "http")).build();

But just a reminder, you should have some sort of authentication for your OpenSearch cluster to protect your data.

OpenSearchClient for AWS environment:

I wanted to show you the easiest way to connect to an AWS hosted OpenSearch cluster. The endpoint would be accessible using some AWS credentials like secret id & key, IAM role etc. Secret id & key would already be configured as part of the application & it will be available as part of credential provider chain. IAM role is even better where you won’t have to maintain separate set of secret id & key.

AWS provides a JAVA SDK which can be used to utilize the already configured AWS credentials & create a client that will automatically sign the API requests to OpenSearch cluster

For this, we would need below dependencies in build.gradle file.

    api 'org.opensearch.client:opensearch-java:2.1.0'
    implementation 'software.amazon.awssdk:http-client-spi:2.17.275'
    implementation 'software.amazon.awssdk:apache-client:2.17.275'
    implementation 'software.amazon.awssdk:regions:2.17.275'
    implementation 'software.amazon.awssdk:auth:2.17.275'

Java code for instantiating client for AWS OpenSearch cluster is given below.

import org.opensearch.client.opensearch.OpenSearchClient;
import org.opensearch.client.transport.aws.AwsSdk2Transport;
import org.opensearch.client.transport.aws.AwsSdk2TransportOptions;

import software.amazon.awssdk.http.SdkHttpClient;
import software.amazon.awssdk.http.apache.ApacheHttpClient;
import software.amazon.awssdk.regions.Region;

public class OpenSearchClientFactory {

	private static OpenSearchClient openSearchClient;

	static {
		openSearchClient = createAWSOpenSearchClient();
	}

	private static OpenSearchClient createAWSOpenSearchClientInstance() {
		SdkHttpClient httpClient = ApacheHttpClient.builder().build();
		return new OpenSearchClient(
				new AwsSdk2Transport(httpClient, "vpc-test-w3spot-gffyfyut6hjhjgjg.us-west-2.es.amazonaws.com",
						Region.of("us-west-2"), AwsSdk2TransportOptions.builder().build()));
	}

	public static OpenSearchClient getInstance() {
		return openSearchClient;
	}

}

This client object would use the underlying AWS credentials chain defined in the application & sign the AWS API requests to OpenSearch endpoint automatically.

Both these clients (non-AWS & AWS) are thread-safe & can be used across multiple requests. A single instance per application should suffice in common cases. By the way, I have hardcoded username/password in the code as an example. That should be kept separately as secret.

Leave a Comment