[[elasticsearch.clients]]
= Elasticsearch Clients

This chapter illustrates configuration and usage of supported Elasticsearch client implementations.

Spring data Elasticsearch operates upon an Elasticsearch client that is connected to a single Elasticsearch node or a cluster. Although the Elasticsearch Client can be used to work with the cluster,  applications using Spring Data Elasticsearch normally use the higher level abstractions of <<elasticsearch.operations>> and <<elasticsearch.repositories>>.

[[elasticsearch.clients.transport]]
== Transport Client

WARNING: The well known `TransportClient` is deprecated as of Elasticsearch 7 and will be removed in Elasticsearch 8. (https://www.elastic.co/guide/en/elasticsearch/client/java-api/current/transport-client.html[see the Elasticsearch documentation]). Spring Data Elasticsearch will support the `TransportClient` as long as it is available in the used
Elasticsearch <<elasticsearch.versions,version>>.

We strongly recommend to use the <<elasticsearch.clients.rest>> instead of the `TransportClient`.

.Transport Client
====
[source,java]
----
static class Config {

  @Bean
  Client client() {
  	Settings settings = Settings.builder()
  	  .put("cluster.name", "elasticsearch")   <1>
      .build();
  	TransportClient client = new PreBuiltTransportClient(settings);
    client.addTransportAddress(new TransportAddress(InetAddress.getByName("127.0.0.1")
      , 9300));                               <2>
    return client;
  }
}

// ...

IndexRequest request = new IndexRequest("spring-data", "elasticsearch", randomID())
 .source(someObject)
 .setRefreshPolicy(IMMEDIATE);

IndexResponse response = client.index(request);
----
<1> The `TransportClient` must be configured with the cluster name.
<2> The host and port to connect the client to.
====

[[elasticsearch.clients.rest]]
== High Level REST Client

The Java High Level REST Client now is the default client of Elasticsearch, it provides a straight forward replacement for the `TransportClient` as it accepts and returns
the very same request/response objects and therefore depends on the Elasticsearch core project.
Asynchronous calls are operated upon a client managed thread pool and require a callback to be notified when the request is done.

.High Level REST Client
====
[source,java]
----
import org.springframework.beans.factory.annotation.Autowired;@Configuration
static class Config {

  @Bean
  RestHighLevelClient client() {

    ClientConfiguration clientConfiguration = ClientConfiguration.builder() <1>
      .connectedTo("localhost:9200", "localhost:9201")
      .build();

    return RestClients.create(clientConfiguration).rest();                  <2>
  }
}

// ...

  @Autowired
  RestHighLevelClient highLevelClient;

  RestClient lowLevelClient = highLevelClient.lowLevelClient();             <3>

// ...

IndexRequest request = new IndexRequest("spring-data", "elasticsearch", randomID())
  .source(singletonMap("feature", "high-level-rest-client"))
  .setRefreshPolicy(IMMEDIATE);

IndexResponse response = highLevelClient.index(request);
----
<1> Use the builder to provide cluster addresses, set default `HttpHeaders` or enable SSL.
<2> Create the RestHighLevelClient.
<3> It is also possible to obtain the `lowLevelRest()` client.
====

[[elasticsearch.clients.reactive]]
== Reactive Client

The `ReactiveElasticsearchClient` is a non official driver based on `WebClient`.
It uses the request/response objects provided by the Elasticsearch core project.
Calls are directly operated on the reactive stack, **not** wrapping async (thread pool bound) responses into reactive types.

.Reactive REST Client
====
[source,java]
----
static class Config {

  @Bean
  ReactiveElasticsearchClient client() {

    ClientConfiguration clientConfiguration = ClientConfiguration.builder()   <1>
      .connectedTo("localhost:9200", "localhost:9291")
      .withWebClientConfigurer(webClient -> {                                 <2>
        ExchangeStrategies exchangeStrategies = ExchangeStrategies.builder()
            .codecs(configurer -> configurer.defaultCodecs()
                .maxInMemorySize(-1))
            .build();
        return webClient.mutate().exchangeStrategies(exchangeStrategies).build();
       })
      .build();

    return ReactiveRestClients.create(clientConfiguration);
  }
}

// ...

Mono<IndexResponse> response = client.index(request ->

  request.index("spring-data")
    .type("elasticsearch")
    .id(randomID())
    .source(singletonMap("feature", "reactive-client"))
    .setRefreshPolicy(IMMEDIATE);
);
----
<1> Use the builder to provide cluster addresses, set default `HttpHeaders` or enable SSL.
<2> when configuring a reactive client, the `withWebClientConfigurer` hook can be used to customize the WebClient.
====

NOTE: The ReactiveClient response, especially for search operations, is bound to the `from` (offset) & `size` (limit) options of the request.

[[elasticsearch.clients.configuration]]
== Client Configuration

Client behaviour can be changed via the `ClientConfiguration` that allows to set options for SSL, connect and socket timeouts.

.Client Configuration
====
[source,java]
----
// optional if Basic Auhtentication is needed
HttpHeaders defaultHeaders = new HttpHeaders();
defaultHeaders.setBasicAuth(USER_NAME, USER_PASS);                      <1>

ClientConfiguration clientConfiguration = ClientConfiguration.builder()
  .connectedTo("localhost:9200", "localhost:9291")                      <2>
  .withConnectTimeout(Duration.ofSeconds(5))                            <3>
  .withSocketTimeout(Duration.ofSeconds(3))                             <4>
  .usingSsl()                                                           <5>
  .withDefaultHeaders(defaultHeaders)                                   <6>
  .withBasicAuth(username, password)                                    <7>
  . // ... other options
  .build();

----
<1> Define default headers, if they need to be customized
<2> Use the builder to provide cluster addresses, set default `HttpHeaders` or enable SSL.
<3> Set the connection timeout. Default is 10 sec.
<4> Set the socket timeout. Default is 5 sec.
<5> Optionally enable SSL.
<6> Optionally set headers.
<7> Add basic authentication.
====

[[elasticsearch.clients.logging]]
== Client Logging

To see what is actually sent to and received from the server `Request` / `Response` logging on the transport level needs
to be turned on as outlined in the snippet below.

.Enable transport layer logging
[source,xml]
----
<logger name="org.springframework.data.elasticsearch.client.WIRE" level="trace"/>
----

NOTE: The above applies to both the `RestHighLevelClient` and `ReactiveElasticsearchClient` when obtained via `RestClients` respectively `ReactiveRestClients`, is not available for the `TransportClient`.
