Search code examples
javaspringelasticsearchresthighlevelclient

ElasticSearch RestHighLevelClient save index throws NullPointerException in Java Spring


When I tried to save the data, I get exception like this below, but the data are saved to elastic search I checked with. /index/_search query.

2024-01-21 23:19:28.724 ERROR 14382 --- [nio-8080-exec-2] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.dao.DataAccessResourceFailureException: Unable to parse response body for Response{requestLine=PUT /product/_doc/98?timeout=1m HTTP/1.1, host=http://localhost:9200, response=HTTP/1.1 201 Created}; nested exception is java.lang.RuntimeException: Unable to parse response body for Response{requestLine=PUT /product/_doc/98?timeout=1m HTTP/1.1, host=http://localhost:9200, response=HTTP/1.1 201 Created}] with root cause

java.lang.NullPointerException: null
    at java.base/java.util.Objects.requireNonNull(Objects.java:221) ~[na:na]
    at org.elasticsearch.action.DocWriteResponse.<init>(DocWriteResponse.java:116) ~[elasticsearch-7.15.2.jar:7.15.2]
    at org.elasticsearch.action.index.IndexResponse.<init>(IndexResponse.java:43) ~[elasticsearch-7.15.2.jar:7.15.2]

Facing error like this in RestHighLevelClient configuration.

package com.springPractice.app.configuration;

import org.elasticsearch.client.RestHighLevelClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.elasticsearch.ElasticsearchProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.elasticsearch.client.ClientConfiguration;
import org.springframework.data.elasticsearch.client.RestClients;
import org.springframework.data.elasticsearch.config.AbstractElasticsearchConfiguration;
import org.springframework.http.HttpHeaders;

@Configuration
@ComponentScan(basePackages = {"com.springPractice.app"})
@EnableAutoConfiguration
public class ElasticsearchConfiguration extends AbstractElasticsearchConfiguration {

    private final ElasticsearchProperties elasticsearchProperties;

    @Autowired
    public ElasticsearchConfiguration(ElasticsearchProperties elasticsearchProperties) {
        this.elasticsearchProperties = elasticsearchProperties;
    }

    @Override
    @Bean
    public RestHighLevelClient elasticsearchClient() {
        final ClientConfiguration clientConfiguration = ClientConfiguration.builder()
                .connectedTo("localhost:9200")
                .withSocketTimeout(elasticsearchProperties.getSocketTimeout())
                .build();

        return RestClients.create(clientConfiguration).rest();
    }
}


Solution

  • The issue is because of the content-type returned by the elastic search, to resolve this we can add the below headers to the configuration.

            HttpHeaders compatibilityHeaders = new HttpHeaders();
            compatibilityHeaders.add("Accept", "application/vnd.elasticsearch+json;compatible-with=7");
            compatibilityHeaders.add("Content-Type", "application/vnd.elasticsearch+json;" + "compatible-with=7");
    
    

    So the final configuration code looks like

        @Override
        @Bean
        public RestHighLevelClient elasticsearchClient() {
            HttpHeaders compatibilityHeaders = new HttpHeaders();
            compatibilityHeaders.add("Accept", "application/vnd.elasticsearch+json;compatible-with=7");
            compatibilityHeaders.add("Content-Type", "application/vnd.elasticsearch+json;" + "compatible-with=7");
    
            final ClientConfiguration clientConfiguration = ClientConfiguration.builder()
                    .connectedTo("localhost:9200")
                    .withSocketTimeout(elasticsearchProperties.getSocketTimeout())
                    .withDefaultHeaders(compatibilityHeaders)
                    .build();
    
            return RestClients.create(clientConfiguration).rest();
        }