diff --git a/src/main/asciidoc/reference/elasticsearch-clients.adoc b/src/main/asciidoc/reference/elasticsearch-clients.adoc index aa79e0a9c..5c8fae707 100644 --- a/src/main/asciidoc/reference/elasticsearch-clients.adoc +++ b/src/main/asciidoc/reference/elasticsearch-clients.adoc @@ -38,16 +38,17 @@ ElasticsearchClient elasticsearchClient; <.> @Autowired RestClient restClient; <.> ---- + the following can be injected: -<.> an implementation of `ElasticsearchOperations` -<.> the `co.elastic.clients.elasticsearch.ElasticsearchClient` that is used. This is new Elasticsearch client -implementation. +<.> an implementation of `ElasticsearchOperations` +<.> the `co.elastic.clients.elasticsearch.ElasticsearchClient` that is used. +This is new Elasticsearch client implementation. <.> the low level `RestClient` from the Elasticsearch libraries ==== -Basically one should just use the `ElasticsearchOperations` to interact with the Elasticsearch cluster. When using -repositories, this instance is used under the hood as well. +Basically one should just use the `ElasticsearchOperations` to interact with the Elasticsearch cluster. +When using repositories, this instance is used under the hood as well. [[elasticsearch.clients.reactiverestclient]] == Reactive Rest Client @@ -81,21 +82,22 @@ ReactiveElasticsearchClient elasticsearchClient; <.> @Autowired RestClient restClient; <.> ---- + the following can be injected: <.> an implementation of `ElasticsearchOperations` -<.> the `org.springframework.data.elasticsearch.client.elc.ReactiveElasticsearchClient` that is used. This is based -on the new Elasticsearch client implementation. +<.> the `org.springframework.data.elasticsearch.client.elc.ReactiveElasticsearchClient` that is used. +This is based on the new Elasticsearch client implementation. <.> the low level `RestClient` from the Elasticsearch libraries ==== -Basically one should just use the `ReactiveElasticsearchOperations` to interact with the Elasticsearch cluster. When -using repositories, this instance is used under the hood as well. +Basically one should just use the `ReactiveElasticsearchOperations` to interact with the Elasticsearch cluster. +When using repositories, this instance is used under the hood as well. [[elasticsearch.clients.resthighlevelclient]] == High Level REST Client (deprecated) -The Java RestHighLevelClient is deprecated, but still can be configured like shown (read +The Java RestHighLevelClient is deprecated, but still can be configured like shown (read <> as well): .RestHighLevelClient @@ -231,12 +233,49 @@ Default is 5 sec. <.> Optionally set headers. <.> Add basic authentication. <.> A `Supplier
` function can be specified which is called every time before a request is sent to Elasticsearch - here, as an example, the current time is written in a header. -<.> a function configuring the low level REST client (the same for the imperative and reactive stack) +<.> a function to configure the created client (see <>), can be added multiple times. ==== IMPORTANT: Adding a Header supplier as shown in above example allows to inject headers that may change over the time, like authentication JWT tokens. If this is used in the reactive setup, the supplier function *must not* block! +[[elasticsearch.clients.configuration.callbacks]] +=== Client configuration callbacks + +The `ClientConfiguration` class offers the most common parameters to configure the client. In the case this is not +enough, the user can add callback functions by using the `withClientConfigurer(ClientConfigurationCallback)` method. + +The following callbacks are provided: + +==== Configuration of the low level Elasticsearch `RestClient`: + +==== +[source,java] +---- +ClientConfiguration.builder() + .withClientConfigurer(ElasticsearchClients.ElasticsearchRestClientConfigurationCallback.from(restClientBuilder -> { + // configure the Elasticsearch RestClient + return restClientBuilder; + })) + .build(); +---- +==== + +==== Configuration of the HttpAsyncClient used by the low level Elasticsearch `RestClient`: + +==== +[source,java] +---- +ClientConfiguration.builder() + .withClientConfigurer(ElasticsearchClients.ElasticsearchHttpClientConfigurationCallback.from(httpAsyncClientBuilder -> { + // configure the HttpAsyncClient + return httpAsyncClientBuilder; + })) + .build(); +---- +==== + + === Elasticsearch 7 compatibility headers When using the deprecated `RestHighLevelClient` and accessing an Elasticsearch cluster that is running on version 8, it is necessary to set the compatibility headers diff --git a/src/main/asciidoc/reference/elasticsearch-migration-guide-4.4-5.0.adoc b/src/main/asciidoc/reference/elasticsearch-migration-guide-4.4-5.0.adoc index f136f58ec..aa2ce6bf7 100644 --- a/src/main/asciidoc/reference/elasticsearch-migration-guide-4.4-5.0.adoc +++ b/src/main/asciidoc/reference/elasticsearch-migration-guide-4.4-5.0.adoc @@ -36,7 +36,7 @@ If you are using `ElasticsearchRestTemplate` directly and not the `Elasticsearch adjust your imports as well. When working with the `NativeSearchQuery` class, you'll need to switch to the `NativeQuery` class, which can take a -`Query` instance comign from the new Elasticsearch client libraries. You'll find plenty of examples in the test code. +`Query` instance comign from the new Elasticsearch client libraries. You'll find plenty of examples in the test code. [[elasticsearch-migration-guide-4.4-5.0.new-clients]] == New Elasticsearch client diff --git a/src/main/java/org/springframework/data/elasticsearch/client/elc/ElasticsearchClients.java b/src/main/java/org/springframework/data/elasticsearch/client/elc/ElasticsearchClients.java index 53d434fb0..5ac223102 100644 --- a/src/main/java/org/springframework/data/elasticsearch/client/elc/ElasticsearchClients.java +++ b/src/main/java/org/springframework/data/elasticsearch/client/elc/ElasticsearchClients.java @@ -56,7 +56,6 @@ import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.lang.Nullable; import org.springframework.util.Assert; -import org.springframework.web.reactive.function.client.WebClient; /** * Utility class to create the different Elasticsearch clients @@ -229,14 +228,20 @@ public final class ElasticsearchClients { for (ClientConfiguration.ClientConfigurationCallback clientConfigurer : clientConfiguration .getClientConfigurers()) { - if (clientConfigurer instanceof ElasticsearchClientConfigurationCallback) { - ElasticsearchClientConfigurationCallback restClientConfigurationCallback = (ElasticsearchClientConfigurationCallback) clientConfigurer; + if (clientConfigurer instanceof ElasticsearchHttpClientConfigurationCallback restClientConfigurationCallback) { clientBuilder = restClientConfigurationCallback.configure(clientBuilder); } } return clientBuilder; }); + + for (ClientConfiguration.ClientConfigurationCallback clientConfigurationCallback : clientConfiguration + .getClientConfigurers()) { + if (clientConfigurationCallback instanceof ElasticsearchRestClientConfigurationCallback configurationCallback) { + builder = configurationCallback.configure(builder); + } + } return builder; } @@ -360,37 +365,39 @@ public final class ElasticsearchClients { /** * {@link org.springframework.data.elasticsearch.client.ClientConfiguration.ClientConfigurationCallback} to configure - * the RestClient with a {@link HttpAsyncClientBuilder} + * the Elasticsearch RestClient's Http client with a {@link HttpAsyncClientBuilder} * * @since 4.4 */ - public interface ElasticsearchClientConfigurationCallback + public interface ElasticsearchHttpClientConfigurationCallback extends ClientConfiguration.ClientConfigurationCallback { - static ElasticsearchClientConfigurationCallback from( - Function clientBuilderCallback) { + static ElasticsearchHttpClientConfigurationCallback from( + Function httpClientBuilderCallback) { - Assert.notNull(clientBuilderCallback, "clientBuilderCallback must not be null"); + Assert.notNull(httpClientBuilderCallback, "httpClientBuilderCallback must not be null"); // noinspection NullableProblems - return clientBuilderCallback::apply; + return httpClientBuilderCallback::apply; } } /** * {@link org.springframework.data.elasticsearch.client.ClientConfiguration.ClientConfigurationCallback} to configure - * the ReactiveElasticsearchClient with a {@link WebClient} + * the RestClient client with a {@link RestClientBuilder} * - * @since 4.4 + * @since 5.0 */ - public interface WebClientConfigurationCallback extends ClientConfiguration.ClientConfigurationCallback { + public interface ElasticsearchRestClientConfigurationCallback + extends ClientConfiguration.ClientConfigurationCallback { - static WebClientConfigurationCallback from(Function webClientCallback) { + static ElasticsearchRestClientConfigurationCallback from( + Function restClientBuilderCallback) { - Assert.notNull(webClientCallback, "webClientCallback must not be null"); + Assert.notNull(restClientBuilderCallback, "restClientBuilderCallback must not be null"); // noinspection NullableProblems - return webClientCallback::apply; + return restClientBuilderCallback::apply; } } } diff --git a/src/main/java/org/springframework/data/elasticsearch/client/erhlc/ReactiveRestClients.java b/src/main/java/org/springframework/data/elasticsearch/client/erhlc/ReactiveRestClients.java index 1344790fd..aa77d4f79 100644 --- a/src/main/java/org/springframework/data/elasticsearch/client/erhlc/ReactiveRestClients.java +++ b/src/main/java/org/springframework/data/elasticsearch/client/erhlc/ReactiveRestClients.java @@ -72,7 +72,9 @@ public final class ReactiveRestClients { * the ReactiveElasticsearchClient with a {@link WebClient} * * @since 4.3 + * @deprecated */ + @Deprecated public interface WebClientConfigurationCallback extends ClientConfiguration.ClientConfigurationCallback { static WebClientConfigurationCallback from(Function webClientCallback) { diff --git a/src/main/java/org/springframework/data/elasticsearch/client/erhlc/RestClients.java b/src/main/java/org/springframework/data/elasticsearch/client/erhlc/RestClients.java index a3f5eee4c..eff13559a 100644 --- a/src/main/java/org/springframework/data/elasticsearch/client/erhlc/RestClients.java +++ b/src/main/java/org/springframework/data/elasticsearch/client/erhlc/RestClients.java @@ -252,7 +252,9 @@ public final class RestClients { * the RestClient with a {@link HttpAsyncClientBuilder} * * @since 4.3 + * @deprecated since 5.0 */ + @Deprecated public interface RestClientConfigurationCallback extends ClientConfiguration.ClientConfigurationCallback { diff --git a/src/main/java/org/springframework/data/elasticsearch/client/erhlc/WebClientProvider.java b/src/main/java/org/springframework/data/elasticsearch/client/erhlc/WebClientProvider.java index 47cba4f90..748f94c82 100644 --- a/src/main/java/org/springframework/data/elasticsearch/client/erhlc/WebClientProvider.java +++ b/src/main/java/org/springframework/data/elasticsearch/client/erhlc/WebClientProvider.java @@ -35,7 +35,6 @@ import java.util.function.Function; import javax.net.ssl.SSLContext; import org.springframework.data.elasticsearch.client.ClientConfiguration; -import org.springframework.data.elasticsearch.client.elc.ElasticsearchClients; import org.springframework.http.HttpHeaders; import org.springframework.http.client.reactive.ClientHttpConnector; import org.springframework.http.client.reactive.ReactorClientHttpConnector; @@ -240,11 +239,6 @@ public interface WebClientProvider { ReactiveRestClients.WebClientConfigurationCallback webClientConfigurationCallback = (ReactiveRestClients.WebClientConfigurationCallback) clientConfigurer; webClient = webClientConfigurationCallback.configure(webClient); } - - if (clientConfigurer instanceof ElasticsearchClients.WebClientConfigurationCallback) { - ElasticsearchClients.WebClientConfigurationCallback webClientConfigurationCallback = (ElasticsearchClients.WebClientConfigurationCallback) clientConfigurer; - webClient = webClientConfigurationCallback.configure(webClient); - } } return webClient; }; diff --git a/src/test/java/org/springframework/data/elasticsearch/client/RestClientsTest.java b/src/test/java/org/springframework/data/elasticsearch/client/RestClientsTest.java index 01dafd26b..15063621a 100644 --- a/src/test/java/org/springframework/data/elasticsearch/client/RestClientsTest.java +++ b/src/test/java/org/springframework/data/elasticsearch/client/RestClientsTest.java @@ -103,7 +103,8 @@ public class RestClientsTest { defaultHeaders.add("def2", "def2-1"); AtomicInteger supplierCount = new AtomicInteger(1); - AtomicInteger clientConfigurerCount = new AtomicInteger(0); + AtomicInteger httpClientConfigurerCount = new AtomicInteger(0); + AtomicInteger restClientConfigurerCount = new AtomicInteger(0); ClientConfigurationBuilder configurationBuilder = new ClientConfigurationBuilder(); configurationBuilder // @@ -120,26 +121,36 @@ public class RestClientsTest { if (clientUnderTestFactory instanceof ERHLCUnderTestFactory) { configurationBuilder .withClientConfigurer(RestClients.RestClientConfigurationCallback.from(httpClientBuilder -> { - clientConfigurerCount.incrementAndGet(); + httpClientConfigurerCount.incrementAndGet(); return httpClientBuilder; })); } else if (clientUnderTestFactory instanceof ReactiveERHLCUnderTestFactory) { configurationBuilder.withClientConfigurer(ReactiveRestClients.WebClientConfigurationCallback.from(webClient -> { - clientConfigurerCount.incrementAndGet(); + httpClientConfigurerCount.incrementAndGet(); return webClient; })); } else if (clientUnderTestFactory instanceof ELCUnderTestFactory) { configurationBuilder.withClientConfigurer( - ElasticsearchClients.ElasticsearchClientConfigurationCallback.from(httpClientBuilder -> { - clientConfigurerCount.incrementAndGet(); + ElasticsearchClients.ElasticsearchHttpClientConfigurationCallback.from(httpClientBuilder -> { + httpClientConfigurerCount.incrementAndGet(); return httpClientBuilder; })); + configurationBuilder.withClientConfigurer( + ElasticsearchClients.ElasticsearchRestClientConfigurationCallback.from(restClientBuilder -> { + restClientConfigurerCount.incrementAndGet(); + return restClientBuilder; + })); } else if (clientUnderTestFactory instanceof ReactiveELCUnderTestFactory) { configurationBuilder - .withClientConfigurer(ElasticsearchClients.ElasticsearchClientConfigurationCallback.from(webClient -> { - clientConfigurerCount.incrementAndGet(); + .withClientConfigurer(ElasticsearchClients.ElasticsearchHttpClientConfigurationCallback.from(webClient -> { + httpClientConfigurerCount.incrementAndGet(); return webClient; })); + configurationBuilder.withClientConfigurer( + ElasticsearchClients.ElasticsearchRestClientConfigurationCallback.from(restClientBuilder -> { + restClientConfigurerCount.incrementAndGet(); + return restClientBuilder; + })); } ClientConfiguration clientConfiguration = configurationBuilder.build(); @@ -162,7 +173,8 @@ public class RestClientsTest { ); } - assertThat(clientConfigurerCount).hasValue(1); + assertThat(httpClientConfigurerCount).hasValue(1); + assertThat(restClientConfigurerCount).hasValue(clientUnderTestFactory.getExpectedRestClientConfigCalls()); }); } @@ -328,11 +340,16 @@ public class RestClientsTest { } protected abstract String getDisplayName(); + + protected Integer getExpectedRestClientConfigCalls() { + return 0; + } } /** * {@link ClientUnderTestFactory} implementation for the old {@link RestHighLevelClient}. */ + @Deprecated static class ERHLCUnderTestFactory extends ClientUnderTestFactory { @Override @@ -363,7 +380,6 @@ public class RestClientsTest { } }; } - } /** @@ -376,6 +392,11 @@ public class RestClientsTest { return "ElasticsearchClient"; } + @Override + protected Integer getExpectedRestClientConfigCalls() { + return 1; + } + @Override ClientUnderTest create(ClientConfiguration clientConfiguration) { @@ -403,6 +424,7 @@ public class RestClientsTest { * {@link ClientUnderTestFactory} implementation for the * {@link org.springframework.data.elasticsearch.client.erhlc.ReactiveElasticsearchClient}. */ + @Deprecated static class ReactiveERHLCUnderTestFactory extends ClientUnderTestFactory { @Override @@ -446,6 +468,11 @@ public class RestClientsTest { return "ReactiveElasticsearchClient (ELC based)"; } + @Override + protected Integer getExpectedRestClientConfigCalls() { + return 1; + } + @Override ClientUnderTest create(ClientConfiguration clientConfiguration) {