Move ReactiveElasticsearchClient auto-config to correct module

Closes gh-47848
This commit is contained in:
Andy Wilkinson
2025-11-14 09:39:46 +00:00
parent 8a52f4931b
commit e6f6ee78da
11 changed files with 60 additions and 159 deletions
@@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.springframework.boot.elasticsearch.autoconfigure;
package org.springframework.boot.data.elasticsearch.autoconfigure;
import java.util.Map;
@@ -27,7 +27,8 @@ import org.testcontainers.junit.jupiter.Testcontainers;
import reactor.core.publisher.Mono;
import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.jackson.autoconfigure.JacksonAutoConfiguration;
import org.springframework.boot.elasticsearch.autoconfigure.ElasticsearchClientAutoConfiguration;
import org.springframework.boot.elasticsearch.autoconfigure.ElasticsearchRestClientAutoConfiguration;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import org.springframework.boot.testsupport.container.TestImage;
import org.springframework.data.elasticsearch.client.elc.ReactiveElasticsearchClient;
@@ -35,20 +36,20 @@ import org.springframework.data.elasticsearch.client.elc.ReactiveElasticsearchCl
import static org.assertj.core.api.Assertions.assertThat;
/**
* Integration tests for {@link ElasticsearchReactiveClientAutoConfiguration}.
* Integration tests for {@link DataElasticsearchAutoConfiguration}.
*
* @author Brian Clozel
* @author Andy Wilkinson
*/
@Testcontainers(disabledWithoutDocker = true)
class ElasticsearchReactiveClientAutoConfigurationIntegrationTests {
class DataElasticsearchAutoConfigurationIntegrationTests {
@Container
static final ElasticsearchContainer elasticsearch = TestImage.container(ElasticsearchContainer.class);
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
.withConfiguration(AutoConfigurations.of(JacksonAutoConfiguration.class,
ElasticsearchRestClientAutoConfiguration.class, ElasticsearchReactiveClientAutoConfiguration.class));
.withConfiguration(AutoConfigurations.of(ElasticsearchRestClientAutoConfiguration.class,
ElasticsearchClientAutoConfiguration.class, DataElasticsearchAutoConfiguration.class));
@Test
void reactiveClientCanQueryElasticsearchNode() {
@@ -28,7 +28,6 @@ import org.springframework.boot.data.elasticsearch.domain.city.City;
import org.springframework.boot.data.elasticsearch.domain.city.ReactiveCityRepository;
import org.springframework.boot.data.elasticsearch.domain.empty.EmptyDataPackage;
import org.springframework.boot.elasticsearch.autoconfigure.ElasticsearchClientAutoConfiguration;
import org.springframework.boot.elasticsearch.autoconfigure.ElasticsearchReactiveClientAutoConfiguration;
import org.springframework.boot.elasticsearch.autoconfigure.ElasticsearchRestClientAutoConfiguration;
import org.springframework.boot.test.context.FilteredClassLoader;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
@@ -57,8 +56,7 @@ class DataElasticsearchReactiveRepositoriesAutoConfigurationTests {
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
.withConfiguration(AutoConfigurations.of(ElasticsearchClientAutoConfiguration.class,
ElasticsearchRestClientAutoConfiguration.class,
DataElasticsearchReactiveRepositoriesAutoConfiguration.class, DataElasticsearchAutoConfiguration.class,
ElasticsearchReactiveClientAutoConfiguration.class))
DataElasticsearchReactiveRepositoriesAutoConfiguration.class, DataElasticsearchAutoConfiguration.class))
.withPropertyValues(
"spring.elasticsearch.uris=" + elasticsearch.getHost() + ":" + elasticsearch.getFirstMappedPort(),
"spring.elasticsearch.socket-timeout=30s");
@@ -20,7 +20,6 @@ import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.elasticsearch.autoconfigure.ElasticsearchClientAutoConfiguration;
import org.springframework.boot.elasticsearch.autoconfigure.ElasticsearchReactiveClientAutoConfiguration;
import org.springframework.context.annotation.Import;
import org.springframework.data.elasticsearch.client.elc.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.repository.config.EnableElasticsearchRepositories;
@@ -37,8 +36,7 @@ import org.springframework.data.elasticsearch.repository.config.EnableReactiveEl
* @see EnableElasticsearchRepositories
* @see EnableReactiveElasticsearchRepositories
*/
@AutoConfiguration(
after = { ElasticsearchClientAutoConfiguration.class, ElasticsearchReactiveClientAutoConfiguration.class })
@AutoConfiguration(after = ElasticsearchClientAutoConfiguration.class)
@ConditionalOnClass({ ElasticsearchTemplate.class })
@Import({ DataElasticsearchConfiguration.BaseConfiguration.class,
DataElasticsearchConfiguration.JavaClientConfiguration.class,
@@ -19,6 +19,8 @@ package org.springframework.boot.data.elasticsearch.autoconfigure;
import java.util.Collections;
import co.elastic.clients.elasticsearch.ElasticsearchClient;
import co.elastic.clients.transport.ElasticsearchTransport;
import reactor.core.publisher.Mono;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
@@ -94,11 +96,18 @@ abstract class DataElasticsearchConfiguration {
}
@Configuration(proxyBeanMethods = false)
@ConditionalOnBean(ElasticsearchTransport.class)
@ConditionalOnClass({ ReactiveElasticsearchClient.class, ElasticsearchTransport.class, Mono.class })
static class ReactiveRestClientConfiguration {
@Bean
@ConditionalOnMissingBean
ReactiveElasticsearchClient reactiveElasticsearchClient(ElasticsearchTransport transport) {
return new ReactiveElasticsearchClient(transport);
}
@Bean
@ConditionalOnMissingBean(value = ReactiveElasticsearchOperations.class, name = "reactiveElasticsearchTemplate")
@ConditionalOnBean(ReactiveElasticsearchClient.class)
ReactiveElasticsearchTemplate reactiveElasticsearchTemplate(ReactiveElasticsearchClient client,
ElasticsearchConverter converter) {
return new ReactiveElasticsearchTemplate(client, converter);
@@ -24,8 +24,8 @@ import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.data.elasticsearch.autoconfigure.DataElasticsearchAutoConfiguration;
import org.springframework.boot.data.elasticsearch.health.DataElasticsearchReactiveHealthIndicator;
import org.springframework.boot.elasticsearch.autoconfigure.ElasticsearchReactiveClientAutoConfiguration;
import org.springframework.boot.health.autoconfigure.contributor.CompositeReactiveHealthContributorConfiguration;
import org.springframework.boot.health.autoconfigure.contributor.ConditionalOnEnabledHealthIndicator;
import org.springframework.boot.health.contributor.ReactiveHealthContributor;
@@ -40,7 +40,7 @@ import org.springframework.data.elasticsearch.client.elc.ReactiveElasticsearchCl
* @author Aleksander Lech
* @since 4.0.0
*/
@AutoConfiguration(after = ElasticsearchReactiveClientAutoConfiguration.class)
@AutoConfiguration(after = DataElasticsearchAutoConfiguration.class)
@ConditionalOnClass({ ReactiveElasticsearchClient.class, Flux.class, DataElasticsearchReactiveHealthIndicator.class,
ConditionalOnEnabledHealthIndicator.class })
@ConditionalOnBean(ReactiveElasticsearchClient.class)
@@ -19,6 +19,8 @@ package org.springframework.boot.data.elasticsearch.autoconfigure;
import java.math.BigDecimal;
import java.util.Collections;
import co.elastic.clients.transport.ElasticsearchTransport;
import co.elastic.clients.transport.rest5_client.low_level.Rest5Client;
import org.assertj.core.api.InstanceOfAssertFactories;
import org.jspecify.annotations.Nullable;
import org.junit.jupiter.api.Test;
@@ -27,13 +29,13 @@ import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.autoconfigure.TestAutoConfigurationPackage;
import org.springframework.boot.data.elasticsearch.domain.city.City;
import org.springframework.boot.elasticsearch.autoconfigure.ElasticsearchClientAutoConfiguration;
import org.springframework.boot.elasticsearch.autoconfigure.ElasticsearchReactiveClientAutoConfiguration;
import org.springframework.boot.elasticsearch.autoconfigure.ElasticsearchRestClientAutoConfiguration;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.convert.converter.Converter;
import org.springframework.data.elasticsearch.client.elc.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.client.elc.ReactiveElasticsearchClient;
import org.springframework.data.elasticsearch.client.elc.ReactiveElasticsearchTemplate;
import org.springframework.data.elasticsearch.core.convert.ElasticsearchConverter;
import org.springframework.data.elasticsearch.core.convert.ElasticsearchCustomConversions;
@@ -57,8 +59,7 @@ class DataElasticsearchAutoConfigurationTests {
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
.withConfiguration(AutoConfigurations.of(ElasticsearchRestClientAutoConfiguration.class,
ElasticsearchClientAutoConfiguration.class, DataElasticsearchAutoConfiguration.class,
ElasticsearchReactiveClientAutoConfiguration.class));
ElasticsearchClientAutoConfiguration.class, DataElasticsearchAutoConfiguration.class));
@Test
void defaultRestBeansRegistered() {
@@ -113,6 +114,39 @@ class DataElasticsearchAutoConfigurationTests {
});
}
@Test
void configureWithRestClientShouldCreateTransportAndClient() {
this.contextRunner.withUserConfiguration(RestClientConfiguration.class)
.run((context) -> assertThat(context).hasSingleBean(ReactiveElasticsearchClient.class));
}
@Test
void configureWhenCustomClientShouldBackOff() {
this.contextRunner.withUserConfiguration(RestClientConfiguration.class, CustomClientConfiguration.class)
.run((context) -> assertThat(context).hasSingleBean(ReactiveElasticsearchClient.class)
.hasBean("customClient"));
}
@Configuration(proxyBeanMethods = false)
static class RestClientConfiguration {
@Bean
Rest5Client restClient() {
return mock(Rest5Client.class);
}
}
@Configuration(proxyBeanMethods = false)
static class CustomClientConfiguration {
@Bean
ReactiveElasticsearchClient customClient(ElasticsearchTransport transport) {
return new ReactiveElasticsearchClient(transport);
}
}
@Configuration(proxyBeanMethods = false)
static class CustomElasticsearchCustomConversions {
@@ -21,7 +21,7 @@ import org.junit.jupiter.api.Test;
import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.data.elasticsearch.autoconfigure.DataElasticsearchAutoConfiguration;
import org.springframework.boot.data.elasticsearch.health.DataElasticsearchReactiveHealthIndicator;
import org.springframework.boot.elasticsearch.autoconfigure.ElasticsearchReactiveClientAutoConfiguration;
import org.springframework.boot.elasticsearch.autoconfigure.ElasticsearchClientAutoConfiguration;
import org.springframework.boot.elasticsearch.autoconfigure.ElasticsearchRestClientAutoConfiguration;
import org.springframework.boot.elasticsearch.autoconfigure.health.ElasticsearchRestHealthContributorAutoConfiguration;
import org.springframework.boot.elasticsearch.health.ElasticsearchRestClientHealthIndicator;
@@ -39,7 +39,7 @@ class DataElasticsearchReactiveHealthContributorAutoConfigurationTests {
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
.withConfiguration(AutoConfigurations.of(DataElasticsearchAutoConfiguration.class,
ElasticsearchReactiveClientAutoConfiguration.class, ElasticsearchRestClientAutoConfiguration.class,
ElasticsearchClientAutoConfiguration.class, ElasticsearchRestClientAutoConfiguration.class,
DataElasticsearchReactiveHealthContributorAutoConfiguration.class,
HealthContributorAutoConfiguration.class));
@@ -41,9 +41,6 @@ dependencies {
optional("com.fasterxml.jackson.core:jackson-databind")
optional("jakarta.json.bind:jakarta.json.bind-api")
optional("org.springframework.data:spring-data-elasticsearch") {
exclude group: "org.elasticsearch.client", module: "transport"
}
optional("org.testcontainers:testcontainers-elasticsearch")
optional("tools.jackson.core:jackson-databind")
@@ -1,55 +0,0 @@
/*
* Copyright 2012-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.elasticsearch.autoconfigure;
import co.elastic.clients.transport.ElasticsearchTransport;
import co.elastic.clients.transport.rest5_client.low_level.Rest5Client;
import reactor.core.publisher.Mono;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Import;
import org.springframework.data.elasticsearch.client.elc.ReactiveElasticsearchClient;
/**
* {@link EnableAutoConfiguration Auto-configuration} for Spring Data Elasticsearch's
* reactive client.
*
* @author Brian Clozel
* @since 4.0.0
*/
@AutoConfiguration(after = ElasticsearchClientAutoConfiguration.class)
@ConditionalOnBean(Rest5Client.class)
@ConditionalOnClass({ ReactiveElasticsearchClient.class, ElasticsearchTransport.class, Mono.class })
@EnableConfigurationProperties(ElasticsearchProperties.class)
@Import({ ElasticsearchClientConfigurations.JsonpMapperConfiguration.class,
ElasticsearchClientConfigurations.ElasticsearchTransportConfiguration.class })
public final class ElasticsearchReactiveClientAutoConfiguration {
@Bean
@ConditionalOnMissingBean
@ConditionalOnBean(ElasticsearchTransport.class)
ReactiveElasticsearchClient reactiveElasticsearchClient(ElasticsearchTransport transport) {
return new ReactiveElasticsearchClient(transport);
}
}
@@ -1,4 +1,3 @@
org.springframework.boot.elasticsearch.autoconfigure.ElasticsearchClientAutoConfiguration
org.springframework.boot.elasticsearch.autoconfigure.ElasticsearchReactiveClientAutoConfiguration
org.springframework.boot.elasticsearch.autoconfigure.ElasticsearchRestClientAutoConfiguration
org.springframework.boot.elasticsearch.autoconfigure.health.ElasticsearchRestHealthContributorAutoConfiguration
@@ -1,80 +0,0 @@
/*
* Copyright 2012-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.elasticsearch.autoconfigure;
import co.elastic.clients.transport.rest5_client.low_level.Rest5Client;
import org.junit.jupiter.api.Test;
import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.elasticsearch.client.elc.ReactiveElasticsearchClient;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
/**
* Tests for {@link ElasticsearchReactiveClientAutoConfiguration}.
*
* @author Brian Clozel
* @author Andy Wilkinson
*/
class ElasticsearchReactiveClientAutoConfigurationTests {
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
.withConfiguration(AutoConfigurations.of(ElasticsearchReactiveClientAutoConfiguration.class));
@Test
void configureWithoutRestClientShouldBackOff() {
this.contextRunner.run((context) -> assertThat(context).doesNotHaveBean(ReactiveElasticsearchClient.class));
}
@Test
void configureWithRestClientShouldCreateTransportAndClient() {
this.contextRunner.withUserConfiguration(RestClientConfiguration.class)
.run((context) -> assertThat(context).hasSingleBean(ReactiveElasticsearchClient.class));
}
@Test
void configureWhenCustomClientShouldBackOff() {
this.contextRunner.withUserConfiguration(RestClientConfiguration.class, CustomClientConfiguration.class)
.run((context) -> assertThat(context).hasSingleBean(ReactiveElasticsearchClient.class)
.hasBean("customClient"));
}
@Configuration(proxyBeanMethods = false)
static class RestClientConfiguration {
@Bean
Rest5Client restClient() {
return mock(Rest5Client.class);
}
}
@Configuration(proxyBeanMethods = false)
static class CustomClientConfiguration {
@Bean
ReactiveElasticsearchClient customClient() {
return mock(ReactiveElasticsearchClient.class);
}
}
}