Skip to content

Make JsonpMapper a customizable bean. #2580

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jun 1, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 14 additions & 1 deletion src/main/asciidoc/reference/elasticsearch-clients.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -32,24 +32,31 @@ 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
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.
Expand Down Expand Up @@ -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:

====
Expand All @@ -92,6 +101,9 @@ ReactiveElasticsearchClient elasticsearchClient; <.>

@Autowired
RestClient restClient; <.>

@Autowired
JsonpMapper jsonpMapper; <.>
----

the following can be injected:
Expand All @@ -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.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -24,8 +25,6 @@
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;
Expand Down Expand Up @@ -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}
*
Expand All @@ -75,7 +75,7 @@ public static ReactiveElasticsearchClient createReactive(ClientConfiguration cli

Assert.notNull(clientConfiguration, "clientConfiguration must not be null");

return createReactive(getRestClient(clientConfiguration), null);
return createReactive(getRestClient(clientConfiguration), null, DEFAULT_JSONP_MAPPER);
}

/**
Expand All @@ -90,7 +90,24 @@ public static ReactiveElasticsearchClient createReactive(ClientConfiguration cli

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);
}

/**
Expand All @@ -100,7 +117,7 @@ public static ReactiveElasticsearchClient createReactive(ClientConfiguration cli
* @return the {@link ReactiveElasticsearchClient}
*/
public static ReactiveElasticsearchClient createReactive(RestClient restClient) {
return createReactive(restClient, null);
return createReactive(restClient, null, DEFAULT_JSONP_MAPPER);
}

/**
Expand All @@ -111,8 +128,9 @@ public static ReactiveElasticsearchClient createReactive(RestClient restClient)
* @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));
}

/**
Expand All @@ -122,7 +140,7 @@ public static ReactiveElasticsearchClient createReactive(RestClient restClient,
* @return the {@link ElasticsearchClient}
*/
public static ElasticsearchClient createImperative(ClientConfiguration clientConfiguration) {
return createImperative(getRestClient(clientConfiguration), null);
return createImperative(getRestClient(clientConfiguration), null, DEFAULT_JSONP_MAPPER);
}

/**
Expand All @@ -134,7 +152,7 @@ public static ElasticsearchClient createImperative(ClientConfiguration clientCon
*/
public static ElasticsearchClient createImperative(ClientConfiguration clientConfiguration,
TransportOptions transportOptions) {
return createImperative(getRestClient(clientConfiguration), transportOptions);
return createImperative(getRestClient(clientConfiguration), transportOptions, DEFAULT_JSONP_MAPPER);
}

/**
Expand All @@ -144,22 +162,24 @@ public static ElasticsearchClient createImperative(ClientConfiguration clientCon
* @return the {@link ElasticsearchClient}
*/
public static ElasticsearchClient createImperative(RestClient restClient) {
return createImperative(restClient, null);
return createImperative(restClient, null, DEFAULT_JSONP_MAPPER);
}

/**
* Creates a new imperative {@link ElasticsearchClient}
*
* @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);
}
Expand Down Expand Up @@ -236,7 +256,7 @@ private static RestClientBuilder getRestClientBuilder(ClientConfiguration client
}

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();
Expand All @@ -260,7 +280,7 @@ private static ElasticsearchTransport getElasticsearchTransport(RestClient restC
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) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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();

/**
Expand All @@ -63,14 +66,15 @@ public RestClient elasticsearchRestClient(ClientConfiguration clientConfiguratio
* 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);
}

/**
Expand All @@ -89,6 +93,18 @@ public ElasticsearchOperations elasticsearchOperations(ElasticsearchConverter el
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}
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -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();

/**
Expand All @@ -65,11 +67,11 @@ public RestClient elasticsearchRestClient(ClientConfiguration clientConfiguratio
* @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);
}

/**
Expand All @@ -88,6 +90,18 @@ public ReactiveElasticsearchOperations reactiveElasticsearchOperations(Elasticse
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}
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@
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;
Expand Down Expand Up @@ -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 {
Expand Down