javaelasticsearch

elasticsearch-java:8.15.0 hotThreads method throws TransportException


I used "co.elastic.clients:elasticsearch-java:8.15.0", "org.springframework.boot:3.2.7"

And this is my code.

@Slf4j
@Service
@RequiredArgsConstructor
public class NodeHealthService {

    private final ElasticsearchClient elasticsearchClient;

    public HotThreadsResponse hotThreads() throws Exception {
        return elasticsearchClient.nodes().hotThreads();
    }
}

This code throws exception.

co.elastic.clients.transport.TransportException: node: https://xxxxx/, status: 200, [es/nodes.hot_threads] Expecting JSON data but response content-type is: text/plain; charset=UTF-8

enter image description here

The ElasticsearchClient configuration code is as follows:

@Configuration
public class ElasticJavaClientConfig {

    private final static int ES_CONNECTION_TIMEOUT = 5000;
    private final static int ES_SOCKET_TIMEOUT = 60000;

    @Bean
    public RestClient restClient(ElasticsearchInfoProperty elasticsearchInfoProperty) {
        final URI uri = URI.create(elasticsearchInfoProperty.url());
        final String protocol = uri.getScheme();
        final String host = uri.getHost();
        final int port = uri.getPort();
        final String username = elasticsearchInfoProperty.username();
        final String password = elasticsearchInfoProperty.password();
        final CredentialsProvider credentialsProvider = new BasicCredentialsProvider();

        credentialsProvider.setCredentials(
            AuthScope.ANY, new UsernamePasswordCredentials(username, password));

        HttpHost httpHost = new HttpHost(host, port, protocol);

        List<Header> requestHeaders = RequestOptions.DEFAULT.toBuilder()
            .addHeader(org.springframework.http.HttpHeaders.HOST, host)
            .build()
            .getHeaders();

        return RestClient.builder(httpHost)
            .setDefaultHeaders(requestHeaders.toArray(new Header[]{}))
            .setHttpClientConfigCallback(
                httpClientBuilder -> {
                    httpClientBuilder.disableAuthCaching();
                    httpClientBuilder.setKeepAliveStrategy((httpResponse, httpContext) -> 300);
                    return httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider);
                })
            .setRequestConfigCallback(
                requestConfigBuilder -> requestConfigBuilder
                    .setConnectTimeout(ES_CONNECTION_TIMEOUT)
                    .setSocketTimeout(ES_SOCKET_TIMEOUT)).build();
    }

    @Bean
    public ElasticsearchClient elasticsearchClient(RestClient restClient) {
        ElasticsearchTransport transport = new RestClientTransport(restClient, new SimpleJsonpMapper());
        return new ElasticsearchClient(transport);
    }
}

What should I do to make it work properly?

I Want to make the code not throw exception.


Solution

  • Yes. That's a bug. This API does not return JSON but a result in text format. The Java client tries to parse it as JSON, which fails.

    The workaround is to call /_nodes/hot_threads with the RestClient.

    See also https://github.com/elastic/elasticsearch-java/issues/865