Connecting Spring Boot to Elasticsearch via HTTPS with Self-Signed Certificates

Before diving into the code, ensure your Elasticsearch server is running. Open a terminal and execute the elasticsearch command to start the server.

Understanding the Two REST Client Types

Elasticsearch provides two distinct REST client implementations:

High-Level REST Client (RestHighLevelClient): This wrapper handles serialization and deserialization automatically. Developers interact with higher-level abstractions like Index and Document objects, making it the preferred choice for most use cases due to its simplicity.

Low-Level REST Client (RestLowLevelClient): This client works directly with raw HTTP requests and responses. All JSON serialization/deserialization must be handled manually by the developer, offering maximum flexibility but requiring more code.

Auto-Configuration Behavior in Spring Boot

When Spring Boot detects the elasticsearch-rest-high-level-client dependency on the classpath, it automatically configures a RestHighLevelClient bean. Notably, this auto-configuration works without requiring Spring Data Elasticsearch.

To access the low-level client, simply call getLowLevelClient() on the high-level client instance.

Key Takeaways:

  • Spring Boot auto-configures RestHighLevelClient
  • RestLowLevelClient is accessible via the high-level client

Auto-Configuration Classes Overview

Spring Boot provides six auto-configuration classes for Elasticsearch:

  • ElasticsearchRestClientAutoConfiguration: Configures RestClientBuilder, RestClientBuilderCustomizer, and RestHighLevelClient
  • ElasticsearchDataAutoConfiguration: Requires Spring Data Elasticsearch; configures ElasticsearchRestTemplate
  • ElasticsearchRepositoriesAutoConfiguration: Enables repository support
  • ReactiveElasticsearchRestClientAutoConfiguration: Reactive variant for the rest client
  • ReactiveElasticsearchDataAutoConfiguration: Reactive variant for data operations
  • ReactiveElasticsearchRepositoriesAutoConfiguration: Reactive repository support

Common RestHighLevelClient Operations

The RestHighLevelClient provides both synchronous and asynchronous versions of each method. Synchronous methods block until completion, while async methods use callbacks for result handling.

Document Count:

count(CountRequest request, RequestOptions options)
countAsync(CountRequest request, RequestOptions options, ActionListener<CountResponse> listener)

Document Retrieval:

get(GetRequest request, RequestOptions options)
getAsync(GetRequest request, RequestOptions options, ActionListener<GetResponse> listener)
mget(MultiGetRequest request, RequestOptions options)

Document Creation/Updates:

index(IndexRequest request, RequestOptions options)
indexAsync(IndexRequest request, RequestOptions options, ActionListener<IndexResponse> listener)
update(UpdateRequest request, RequestOptions options)
updateAsync(UpdateRequest request, RequestOptions options, ActionListener&ltlt;UpdateResponse> listener)

Document Deletion:

delete(DeleteRequest request, RequestOptions options)
deleteAsync(DeleteRequest request, RequestOptions options, ActionListener<DeleteResponse> listener)
deleteByQuery(DeleteByQueryRequest request, RequestOptions options)

Search Operations:

search(SearchRequest request, RequestOptions options)
searchAsync(SearchRequest request, RequestOptions options, ActionListener<SearchResponse> listener)
msearch(MultiSearchRequest request, RequestOptions options)

Utility Methods:

exists(GetRequest request, RequestOptions options)
updateByQuery(UpdateByQueryRequest request, RequestOptions options)

API Design Pattern

Most methods follow a consistent pattern: they accept an XxxRequest object containing primary request data and a RequestOptions object for additional configuration. Async variants replace RequestOptions with an ActionListener callback.

The client also provides factory methods returning specialized clients: indices() returns IndicesClient, cluster() returns ClusterClient, asyncSearch() returns AsyncSearchClient, and eql() returns EqlClient.

Setting Up HTTPS Connections to Elasticsearch

Scenario Overview

This section demonstrates configuring a Spring Boot application to connect to an Elasticsearch server using HTTPS with a self-signed certificate. When using certificates from trusted Certificate Authorities, Spring Boot handles trust automatically. Self-signed certificates require addisional configuration.

Step 1: Create a Spring Boot Project

Step 2: Configure Elasticsearch Connection

The ElasticsearchRestClientProperties class handles properties prefixed with spring.elasticsearch.rest.*:

# Elasticsearch server endpoint using HTTPS
spring.elasticsearch.rest.uris=https://127.0.0.1:9200
spring.elasticsearch.rest.read-timeout=10s

# Authentication credentials
spring.elasticsearch.rest.username=elastic
spring.elasticsearch.rest.password=e32147

Step 3: Add Required Dependencies

Add the high-level REST client dependency from Maven Central, ensuring the version matches your Elasticsearch server version:

<dependency>
    <groupId>org.elasticsearch.client</groupId>
    <artifactId>elasticsearch-rest-high-level-client</artifactId>
    <version>7.14.1</version>
</dependency>

Step 4: Configure Trust for Self-Signed Certificates

Since we are using a self-signed certificate, Spring Boot will not automatically trust it. We need to add the certificate to a truststore.

Certificate Import Procedure

Export the public certificate from Elasticsearch's keystore:

keytool -export -alias ca -file elastic.cer -keystore elastic-certificates.p12

Import the certificate into a new truststore:

keytool -import -alias ca -file elastic.cer -keystore elastic.store

Place the truststore in your project's resources directory.

Create a configuration class to register the truststore:

static
{
    String truststoreLocation = new File(
            ApplicationContext.class
                    .getResource("/")
                    .getFile()
    )
            .getParentFile()
            .getAbsolutePath() + "\\classes\\elastic.store";

    System.setProperty("javax.net.ssl.trustStore", truststoreLocation);
    System.setProperty("javax.net.ssl.trustStorePassword", "345678");
}

Complete Implementation

application.properties

# Elasticsearch connection configuration

# Server endpoint (HTTPS)
spring.elasticsearch.rest.uris=https://127.0.0.1:9200
spring.elasticsearch.rest.read-timeout=10s

# Authentication
spring.elasticsearch.rest.username=elastic
spring.elasticsearch.rest.password=123456

ElasticsearchConfig.java

package com.example.elasticsearch.config;

import org.apache.http.client.config.RequestConfig;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.impl.nio.client.HttpAsyncClientBuilder;
import org.elasticsearch.client.RestClientBuilder;
import org.springframework.boot.autoconfigure.elasticsearch.RestClientBuilderCustomizer;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.io.File;

@Configuration(proxyBeanMethods = false)
public class ElasticsearchConfiguration
{
    static
    {
        String keystorePath = new File(
                ApplicationContext.class
                        .getResource("/")
                        .getFile()
        )
                .getParentFile()
                .getAbsolutePath() + "\\classes\\elastic.store";

        System.setProperty("javax.net.ssl.trustStore", keystorePath);
        System.setProperty("javax.net.ssl.trustStorePassword", "123456");
    }

    @Bean
    public RestClientBuilderCustomizer restClientBuilderCustomizer()
    {
        return new RestClientBuilderCustomizer()
        {
            @Override
            public void customize(RestClientBuilder builder)
            {
                // Builder customization if needed
            }

            @Override
            public void customize(HttpAsyncClientBuilder builder)
            {
                // Skip hostname verification for local development
                builder.setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE);
            }

            @Override
            public void customize(RequestConfig.Builder builder)
            {
                // Request config customization if needed
            }
        };
    }
}

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" 
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
         https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.4.5</version>
    </parent>

    <groupId>com.example</groupId>
    <artifactId>elasticsearch-client-demo</artifactId>
    <version>1.0.0</version>
    <name>elasticsearch-client-demo</name>

    <properties>
        <java.version>11</java.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>

        <dependency>
            <groupId>org.elasticsearch.client</groupId>
            <artifactId>elasticsearch-rest-high-level-client</artifactId>
            <version>7.14.1</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

Tags: elasticsearch rest-client spring-boot HTTPS ssl

Posted on Wed, 17 Jun 2026 17:30:22 +0000 by priya_amb