Make JsonpMapper a customizable bean.

Original Pull Request #2580
Closes #2566
This commit is contained in:
Peter-Josef Meisch 2023-06-01 12:24:59 +02:00 committed by GitHub
parent f558822545
commit 1d8867be60
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 91 additions and 24 deletions

View File

@ -32,12 +32,15 @@ public class MyClientConfig extends ElasticsearchConfiguration {
<.> for a detailed description of the builder methods see <<elasticsearch.clients.configuration>>
====
The `ElasticsearchConfiguration` class allows further configuration by overriding for example the `jsonpMapper()` or `transportOptions()` methods.
The following beans can then be injected in other Spring components:
====
[source,java]
----
@Autowired
import org.springframework.beans.factory.annotation.Autowired;@Autowired
ElasticsearchOperations operations; <.>
@Autowired
@ -45,11 +48,15 @@ ElasticsearchClient elasticsearchClient; <.>
@Autowired
RestClient restClient; <.>
@Autowired
JsonpMapper jsonpMapper; <.>
----
<.> an implementation of `ElasticsearchOperations`
<.> the `co.elastic.clients.elasticsearch.ElasticsearchClient` that is used.
<.> the low level `RestClient` from the Elasticsearch libraries
<.> the `JsonpMapper` user by the Elasticsearch `Transport`
====
Basically one should just use the `ElasticsearchOperations` to interact with the Elasticsearch cluster.
@ -79,6 +86,8 @@ public class MyClientConfig extends ReactiveElasticsearchConfiguration {
<.> for a detailed description of the builder methods see <<elasticsearch.clients.configuration>>
====
The `ReactiveElasticsearchConfiguration` class allows further configuration by overriding for example the `jsonpMapper()` or `transportOptions()` methods.
The following beans can then be injected in other Spring components:
====
@ -92,6 +101,9 @@ ReactiveElasticsearchClient elasticsearchClient; <.>
@Autowired
RestClient restClient; <.>
@Autowired
JsonpMapper jsonpMapper; <.>
----
the following can be injected:
@ -100,6 +112,7 @@ the following can be injected:
<.> the `org.springframework.data.elasticsearch.client.elc.ReactiveElasticsearchClient` that is used.
This is a reactive implementation based on the Elasticsearch client implementation.
<.> the low level `RestClient` from the Elasticsearch libraries
<.> the `JsonpMapper` user by the Elasticsearch `Transport`
====
Basically one should just use the `ReactiveElasticsearchOperations` to interact with the Elasticsearch cluster.

View File

@ -16,6 +16,7 @@
package org.springframework.data.elasticsearch.client.elc;
import co.elastic.clients.elasticsearch.ElasticsearchClient;
import co.elastic.clients.json.JsonpMapper;
import co.elastic.clients.json.jackson.JacksonJsonpMapper;
import co.elastic.clients.transport.ElasticsearchTransport;
import co.elastic.clients.transport.TransportOptions;
@ -24,8 +25,6 @@ import co.elastic.clients.transport.Version;
import co.elastic.clients.transport.rest_client.RestClientOptions;
import co.elastic.clients.transport.rest_client.RestClientTransport;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.time.Duration;
import java.util.Arrays;
@ -60,11 +59,12 @@ public final class ElasticsearchClients {
/**
* Name of whose value can be used to correlate log messages for this request.
*/
private static final String LOG_ID_ATTRIBUTE = ElasticsearchClients.class.getName() + ".LOG_ID";
private static final String X_SPRING_DATA_ELASTICSEARCH_CLIENT = "X-SpringDataElasticsearch-Client";
private static final String IMPERATIVE_CLIENT = "imperative";
private static final String REACTIVE_CLIENT = "reactive";
private static final JsonpMapper DEFAULT_JSONP_MAPPER = new JacksonJsonpMapper();
/**
* Creates a new {@link ReactiveElasticsearchClient}
*
@ -75,7 +75,7 @@ public final class ElasticsearchClients {
Assert.notNull(clientConfiguration, "clientConfiguration must not be null");
return createReactive(getRestClient(clientConfiguration), null);
return createReactive(getRestClient(clientConfiguration), null, DEFAULT_JSONP_MAPPER);
}
/**
@ -90,7 +90,24 @@ public final class ElasticsearchClients {
Assert.notNull(clientConfiguration, "ClientConfiguration must not be null!");
return createReactive(getRestClient(clientConfiguration), transportOptions);
return createReactive(getRestClient(clientConfiguration), transportOptions, DEFAULT_JSONP_MAPPER);
}
/**
* Creates a new {@link ReactiveElasticsearchClient}
*
* @param clientConfiguration configuration options, must not be {@literal null}.
* @param transportOptions options to be added to each request.
* @param jsonpMapper the JsonpMapper to use
* @return the {@link ReactiveElasticsearchClient}
*/
public static ReactiveElasticsearchClient createReactive(ClientConfiguration clientConfiguration,
@Nullable TransportOptions transportOptions, JsonpMapper jsonpMapper) {
Assert.notNull(clientConfiguration, "ClientConfiguration must not be null!");
Assert.notNull(jsonpMapper, "jsonpMapper must not be null");
return createReactive(getRestClient(clientConfiguration), transportOptions, jsonpMapper);
}
/**
@ -100,7 +117,7 @@ public final class ElasticsearchClients {
* @return the {@link ReactiveElasticsearchClient}
*/
public static ReactiveElasticsearchClient createReactive(RestClient restClient) {
return createReactive(restClient, null);
return createReactive(restClient, null, DEFAULT_JSONP_MAPPER);
}
/**
@ -111,8 +128,9 @@ public final class ElasticsearchClients {
* @return the {@link ReactiveElasticsearchClient}
*/
public static ReactiveElasticsearchClient createReactive(RestClient restClient,
@Nullable TransportOptions transportOptions) {
return new ReactiveElasticsearchClient(getElasticsearchTransport(restClient, REACTIVE_CLIENT, transportOptions));
@Nullable TransportOptions transportOptions, JsonpMapper jsonpMapper) {
return new ReactiveElasticsearchClient(
getElasticsearchTransport(restClient, REACTIVE_CLIENT, transportOptions, jsonpMapper));
}
/**
@ -122,7 +140,7 @@ public final class ElasticsearchClients {
* @return the {@link ElasticsearchClient}
*/
public static ElasticsearchClient createImperative(ClientConfiguration clientConfiguration) {
return createImperative(getRestClient(clientConfiguration), null);
return createImperative(getRestClient(clientConfiguration), null, DEFAULT_JSONP_MAPPER);
}
/**
@ -134,7 +152,7 @@ public final class ElasticsearchClients {
*/
public static ElasticsearchClient createImperative(ClientConfiguration clientConfiguration,
TransportOptions transportOptions) {
return createImperative(getRestClient(clientConfiguration), transportOptions);
return createImperative(getRestClient(clientConfiguration), transportOptions, DEFAULT_JSONP_MAPPER);
}
/**
@ -144,7 +162,7 @@ public final class ElasticsearchClients {
* @return the {@link ElasticsearchClient}
*/
public static ElasticsearchClient createImperative(RestClient restClient) {
return createImperative(restClient, null);
return createImperative(restClient, null, DEFAULT_JSONP_MAPPER);
}
/**
@ -152,14 +170,16 @@ public final class ElasticsearchClients {
*
* @param restClient the RestClient to use
* @param transportOptions options to be added to each request.
* @param jsonpMapper the mapper for the transport to use
* @return the {@link ElasticsearchClient}
*/
public static ElasticsearchClient createImperative(RestClient restClient,
@Nullable TransportOptions transportOptions) {
public static ElasticsearchClient createImperative(RestClient restClient, @Nullable TransportOptions transportOptions,
JsonpMapper jsonpMapper) {
Assert.notNull(restClient, "restClient must not be null");
ElasticsearchTransport transport = getElasticsearchTransport(restClient, IMPERATIVE_CLIENT, transportOptions);
ElasticsearchTransport transport = getElasticsearchTransport(restClient, IMPERATIVE_CLIENT, transportOptions,
jsonpMapper);
return new AutoCloseableElasticsearchClient(transport);
}
@ -236,7 +256,7 @@ public final class ElasticsearchClients {
}
private static ElasticsearchTransport getElasticsearchTransport(RestClient restClient, String clientType,
@Nullable TransportOptions transportOptions) {
@Nullable TransportOptions transportOptions, JsonpMapper jsonpMapper) {
TransportOptions.Builder transportOptionsBuilder = transportOptions != null ? transportOptions.toBuilder()
: new RestClientOptions(RequestOptions.DEFAULT).toBuilder();
@ -260,7 +280,7 @@ public final class ElasticsearchClients {
TransportOptions transportOptionsWithHeader = transportOptionsBuilder
.addHeader(X_SPRING_DATA_ELASTICSEARCH_CLIENT, clientType).build();
return new RestClientTransport(restClient, new JacksonJsonpMapper(), transportOptionsWithHeader);
return new RestClientTransport(restClient, jsonpMapper, transportOptionsWithHeader);
}
private static List<String> formattedHosts(List<InetSocketAddress> hosts, boolean useSsl) {

View File

@ -16,11 +16,14 @@
package org.springframework.data.elasticsearch.client.elc;
import co.elastic.clients.elasticsearch.ElasticsearchClient;
import co.elastic.clients.json.JsonpMapper;
import co.elastic.clients.json.jackson.JacksonJsonpMapper;
import co.elastic.clients.transport.TransportOptions;
import co.elastic.clients.transport.rest_client.RestClientOptions;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestClient;
import org.jetbrains.annotations.NotNull;
import org.springframework.context.annotation.Bean;
import org.springframework.data.elasticsearch.client.ClientConfiguration;
import org.springframework.data.elasticsearch.config.ElasticsearchConfigurationSupport;
@ -42,7 +45,7 @@ public abstract class ElasticsearchConfiguration extends ElasticsearchConfigurat
*
* @return configuration, must not be {@literal null}
*/
@Bean(name="elasticsearchClientConfiguration")
@Bean(name = "elasticsearchClientConfiguration")
public abstract ClientConfiguration clientConfiguration();
/**
@ -63,14 +66,15 @@ public abstract class ElasticsearchConfiguration extends ElasticsearchConfigurat
* Provides the {@link ElasticsearchClient} to be used.
*
* @param restClient the low level RestClient to use
* @param jsonpMapper the JsonpMapper to use
* @return ElasticsearchClient instance
*/
@Bean
public ElasticsearchClient elasticsearchClient(RestClient restClient) {
public ElasticsearchClient elasticsearchClient(RestClient restClient, JsonpMapper jsonpMapper) {
Assert.notNull(restClient, "restClient must not be null");
return ElasticsearchClients.createImperative(restClient, transportOptions());
return ElasticsearchClients.createImperative(restClient, transportOptions(), jsonpMapper);
}
/**
@ -89,6 +93,18 @@ public abstract class ElasticsearchConfiguration extends ElasticsearchConfigurat
return template;
}
/**
* Provides the JsonpMapper bean that is used in the {@link #elasticsearchClient(RestClient, JsonpMapper)} method.
* This can be adapted by overriding tge {@link #getJsonpMapper()} method.
*
* @return the {@link JsonpMapper} to use
* @since 5.2
*/
@Bean
public JsonpMapper jsonpMapper() {
return new JacksonJsonpMapper();
}
/**
* @return the options that should be added to every request. Must not be {@literal null}
*/

View File

@ -15,6 +15,8 @@
*/
package org.springframework.data.elasticsearch.client.elc;
import co.elastic.clients.json.JsonpMapper;
import co.elastic.clients.json.jackson.JacksonJsonpMapper;
import co.elastic.clients.transport.TransportOptions;
import co.elastic.clients.transport.rest_client.RestClientOptions;
@ -41,7 +43,7 @@ public abstract class ReactiveElasticsearchConfiguration extends ElasticsearchCo
*
* @return configuration, must not be {@literal null}
*/
@Bean(name="elasticsearchClientConfiguration")
@Bean(name = "elasticsearchClientConfiguration")
public abstract ClientConfiguration clientConfiguration();
/**
@ -65,11 +67,11 @@ public abstract class ReactiveElasticsearchConfiguration extends ElasticsearchCo
* @return ReactiveElasticsearchClient instance.
*/
@Bean
public ReactiveElasticsearchClient reactiveElasticsearchClient(RestClient restClient) {
public ReactiveElasticsearchClient reactiveElasticsearchClient(RestClient restClient, JsonpMapper jsonpMapper) {
Assert.notNull(restClient, "restClient must not be null");
return ElasticsearchClients.createReactive(restClient, transportOptions());
return ElasticsearchClients.createReactive(restClient, transportOptions(), jsonpMapper);
}
/**
@ -88,6 +90,18 @@ public abstract class ReactiveElasticsearchConfiguration extends ElasticsearchCo
return template;
}
/**
* Provides the JsonpMapper that is used in the {@link #reactiveElasticsearchClient(RestClient, JsonpMapper)} method
* and exposes it as a bean.
*
* @return the {@link JsonpMapper} to use
* @since 5.2
*/
@Bean
public JsonpMapper jsonpMapper() {
return new JacksonJsonpMapper();
}
/**
* @return the options that should be added to every request. Must not be {@literal null}
*/

View File

@ -30,6 +30,8 @@ import co.elastic.clients.elasticsearch.indices.ElasticsearchIndicesClient;
import co.elastic.clients.elasticsearch.indices.GetIndicesSettingsRequest;
import co.elastic.clients.elasticsearch.indices.GetIndicesSettingsResponse;
import co.elastic.clients.elasticsearch.indices.IndexSettings;
import co.elastic.clients.json.JsonpMapper;
import co.elastic.clients.json.jackson.JacksonJsonpMapper;
import co.elastic.clients.transport.ElasticsearchTransport;
import co.elastic.clients.transport.TransportOptions;
import co.elastic.clients.transport.rest_client.RestClientOptions;
@ -75,10 +77,12 @@ public class DevTests {
private final TransportOptions transportOptions = new RestClientOptions(RequestOptions.DEFAULT).toBuilder()
.addHeader("X-SpringDataElasticsearch-AlwaysThere", "true").setParameter("pretty", "true").build();
private final JsonpMapper jsonpMapper = new JacksonJsonpMapper();
private final ReactiveElasticsearchClient reactiveElasticsearchClient = ElasticsearchClients
.createReactive(clientConfiguration(), transportOptions);
private final ElasticsearchClient imperativeElasticsearchClient = ElasticsearchClients
.createImperative(ElasticsearchClients.getRestClient(clientConfiguration()), transportOptions);
.createImperative(ElasticsearchClients.getRestClient(clientConfiguration()), transportOptions, jsonpMapper);
@Test
void someTest() throws IOException {