Skip to content

Commit a76aaab

Browse files
committed
Merge pull request #17488 from nosan
* pr/17488: Polish "Create RestClient from a RestHighLevelClient if available" Create RestClient from a RestHighLevelClient if available Closes gh-17488
2 parents bd815f6 + fb0fccf commit a76aaab

File tree

3 files changed

+168
-61
lines changed

3 files changed

+168
-61
lines changed

spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/elasticsearch/rest/RestClientAutoConfiguration.java

Lines changed: 5 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -16,80 +16,27 @@
1616

1717
package org.springframework.boot.autoconfigure.elasticsearch.rest;
1818

19-
import org.apache.http.HttpHost;
20-
import org.apache.http.auth.AuthScope;
21-
import org.apache.http.auth.Credentials;
22-
import org.apache.http.auth.UsernamePasswordCredentials;
23-
import org.apache.http.client.CredentialsProvider;
24-
import org.apache.http.impl.client.BasicCredentialsProvider;
2519
import org.elasticsearch.client.RestClient;
26-
import org.elasticsearch.client.RestClientBuilder;
27-
import org.elasticsearch.client.RestHighLevelClient;
2820

29-
import org.springframework.beans.factory.ObjectProvider;
3021
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
3122
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
32-
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
3323
import org.springframework.boot.context.properties.EnableConfigurationProperties;
34-
import org.springframework.boot.context.properties.PropertyMapper;
35-
import org.springframework.context.annotation.Bean;
3624
import org.springframework.context.annotation.Configuration;
25+
import org.springframework.context.annotation.Import;
3726

3827
/**
3928
* {@link EnableAutoConfiguration Auto-configuration} for Elasticsearch REST clients.
4029
*
4130
* @author Brian Clozel
31+
* @author Stephane Nicoll
4232
* @since 2.1.0
4333
*/
4434
@Configuration
4535
@ConditionalOnClass(RestClient.class)
4636
@EnableConfigurationProperties(RestClientProperties.class)
37+
@Import({ RestClientConfigurations.RestClientBuilderConfiguration.class,
38+
RestClientConfigurations.RestHighLevelClientConfiguration.class,
39+
RestClientConfigurations.RestClientFallbackConfiguration.class })
4740
public class RestClientAutoConfiguration {
4841

49-
private final RestClientProperties properties;
50-
51-
private final ObjectProvider<RestClientBuilderCustomizer> builderCustomizers;
52-
53-
public RestClientAutoConfiguration(RestClientProperties properties,
54-
ObjectProvider<RestClientBuilderCustomizer> builderCustomizers) {
55-
this.properties = properties;
56-
this.builderCustomizers = builderCustomizers;
57-
}
58-
59-
@Bean
60-
@ConditionalOnMissingBean
61-
public RestClient restClient(RestClientBuilder builder) {
62-
return builder.build();
63-
}
64-
65-
@Bean
66-
@ConditionalOnMissingBean
67-
public RestClientBuilder restClientBuilder() {
68-
HttpHost[] hosts = this.properties.getUris().stream().map(HttpHost::create).toArray(HttpHost[]::new);
69-
RestClientBuilder builder = RestClient.builder(hosts);
70-
PropertyMapper map = PropertyMapper.get();
71-
map.from(this.properties::getUsername).whenHasText().to((username) -> {
72-
CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
73-
Credentials credentials = new UsernamePasswordCredentials(this.properties.getUsername(),
74-
this.properties.getPassword());
75-
credentialsProvider.setCredentials(AuthScope.ANY, credentials);
76-
builder.setHttpClientConfigCallback(
77-
(httpClientBuilder) -> httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider));
78-
});
79-
this.builderCustomizers.orderedStream().forEach((customizer) -> customizer.customize(builder));
80-
return builder;
81-
}
82-
83-
@Configuration
84-
@ConditionalOnClass(RestHighLevelClient.class)
85-
public static class RestHighLevelClientConfiguration {
86-
87-
@Bean
88-
@ConditionalOnMissingBean
89-
public RestHighLevelClient restHighLevelClient(RestClientBuilder restClientBuilder) {
90-
return new RestHighLevelClient(restClientBuilder);
91-
}
92-
93-
}
94-
9542
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
/*
2+
* Copyright 2012-2019 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.boot.autoconfigure.elasticsearch.rest;
18+
19+
import org.apache.http.HttpHost;
20+
import org.apache.http.auth.AuthScope;
21+
import org.apache.http.auth.Credentials;
22+
import org.apache.http.auth.UsernamePasswordCredentials;
23+
import org.apache.http.client.CredentialsProvider;
24+
import org.apache.http.impl.client.BasicCredentialsProvider;
25+
import org.elasticsearch.client.RestClient;
26+
import org.elasticsearch.client.RestClientBuilder;
27+
import org.elasticsearch.client.RestHighLevelClient;
28+
29+
import org.springframework.beans.factory.ObjectProvider;
30+
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
31+
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
32+
import org.springframework.boot.context.properties.PropertyMapper;
33+
import org.springframework.context.annotation.Bean;
34+
import org.springframework.context.annotation.Configuration;
35+
36+
/**
37+
* Elasticsearch rest client infrastructure configurations.
38+
*
39+
* @author Brian Clozel
40+
* @author Stephane Nicoll
41+
*/
42+
class RestClientConfigurations {
43+
44+
@Configuration
45+
static class RestClientBuilderConfiguration {
46+
47+
@Bean
48+
@ConditionalOnMissingBean
49+
RestClientBuilder restClientBuilder(RestClientProperties properties,
50+
ObjectProvider<RestClientBuilderCustomizer> builderCustomizers) {
51+
HttpHost[] hosts = properties.getUris().stream().map(HttpHost::create).toArray(HttpHost[]::new);
52+
RestClientBuilder builder = RestClient.builder(hosts);
53+
PropertyMapper map = PropertyMapper.get();
54+
map.from(properties::getUsername).whenHasText().to((username) -> {
55+
CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
56+
Credentials credentials = new UsernamePasswordCredentials(properties.getUsername(),
57+
properties.getPassword());
58+
credentialsProvider.setCredentials(AuthScope.ANY, credentials);
59+
builder.setHttpClientConfigCallback(
60+
(httpClientBuilder) -> httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider));
61+
});
62+
builderCustomizers.orderedStream().forEach((customizer) -> customizer.customize(builder));
63+
return builder;
64+
}
65+
66+
}
67+
68+
@Configuration
69+
@ConditionalOnClass(RestHighLevelClient.class)
70+
static class RestHighLevelClientConfiguration {
71+
72+
@Bean
73+
@ConditionalOnMissingBean
74+
RestHighLevelClient restHighLevelClient(RestClientBuilder restClientBuilder) {
75+
return new RestHighLevelClient(restClientBuilder);
76+
}
77+
78+
@Bean
79+
@ConditionalOnMissingBean
80+
RestClient restClient(RestClientBuilder builder, ObjectProvider<RestHighLevelClient> restHighLevelClient) {
81+
RestHighLevelClient client = restHighLevelClient.getIfUnique();
82+
if (client != null) {
83+
return client.getLowLevelClient();
84+
}
85+
return builder.build();
86+
}
87+
88+
}
89+
90+
@Configuration
91+
static class RestClientFallbackConfiguration {
92+
93+
@Bean
94+
@ConditionalOnMissingBean
95+
RestClient restClient(RestClientBuilder builder) {
96+
return builder.build();
97+
}
98+
99+
}
100+
101+
}

spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/elasticsearch/rest/RestClientAutoConfigurationTests.java

Lines changed: 62 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,13 @@
2424
import org.elasticsearch.action.index.IndexRequest;
2525
import org.elasticsearch.client.RequestOptions;
2626
import org.elasticsearch.client.RestClient;
27+
import org.elasticsearch.client.RestClientBuilder;
2728
import org.elasticsearch.client.RestHighLevelClient;
2829
import org.junit.Test;
2930

3031
import org.springframework.boot.autoconfigure.AutoConfigurations;
3132
import org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchNodeTemplate;
33+
import org.springframework.boot.test.context.FilteredClassLoader;
3234
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
3335
import org.springframework.context.annotation.Bean;
3436
import org.springframework.context.annotation.Configuration;
@@ -49,14 +51,46 @@ public class RestClientAutoConfigurationTests {
4951

5052
@Test
5153
public void configureShouldCreateBothRestClientVariants() {
52-
this.contextRunner.run((context) -> assertThat(context).hasSingleBean(RestClient.class)
53-
.hasSingleBean(RestHighLevelClient.class));
54+
this.contextRunner.run((context) -> {
55+
assertThat(context).hasSingleBean(RestClient.class).hasSingleBean(RestHighLevelClient.class);
56+
assertThat(context.getBean(RestClient.class))
57+
.isSameAs(context.getBean(RestHighLevelClient.class).getLowLevelClient());
58+
});
5459
}
5560

5661
@Test
5762
public void configureWhenCustomClientShouldBackOff() {
5863
this.contextRunner.withUserConfiguration(CustomRestClientConfiguration.class)
59-
.run((context) -> assertThat(context).hasSingleBean(RestClient.class).hasBean("customRestClient"));
64+
.run((context) -> assertThat(context).getBeanNames(RestClient.class).containsOnly("customRestClient"));
65+
}
66+
67+
@Test
68+
public void configureWhenCustomRestHighLevelClientShouldBackOff() {
69+
this.contextRunner.withUserConfiguration(CustomRestHighLevelClientConfiguration.class).run((context) -> {
70+
assertThat(context).hasSingleBean(RestClient.class).hasSingleBean(RestHighLevelClient.class);
71+
assertThat(context.getBean(RestClient.class))
72+
.isSameAs(context.getBean(RestHighLevelClient.class).getLowLevelClient());
73+
});
74+
}
75+
76+
@Test
77+
public void configureWhenDefaultRestClientShouldCreateWhenNoUniqueRestHighLevelClient() {
78+
this.contextRunner.withUserConfiguration(TwoCustomRestHighLevelClientConfiguration.class).run((context) -> {
79+
assertThat(context).hasSingleBean(RestClient.class);
80+
RestClient restClient = context.getBean(RestClient.class);
81+
Map<String, RestHighLevelClient> restHighLevelClients = context.getBeansOfType(RestHighLevelClient.class);
82+
assertThat(restHighLevelClients).hasSize(2);
83+
for (RestHighLevelClient restHighLevelClient : restHighLevelClients.values()) {
84+
assertThat(restHighLevelClient.getLowLevelClient()).isNotSameAs(restClient);
85+
}
86+
});
87+
}
88+
89+
@Test
90+
public void configureWhenHighLevelClientIsNotAvailableShouldCreateRestClientOnly() {
91+
this.contextRunner.withClassLoader(new FilteredClassLoader(RestHighLevelClient.class))
92+
.run((context) -> assertThat(context).hasSingleBean(RestClient.class)
93+
.doesNotHaveBean(RestHighLevelClient.class));
6094
}
6195

6296
@Test
@@ -106,4 +140,29 @@ public RestClientBuilderCustomizer myCustomizer() {
106140

107141
}
108142

143+
@Configuration
144+
static class CustomRestHighLevelClientConfiguration {
145+
146+
@Bean
147+
RestHighLevelClient customRestHighLevelClient(RestClientBuilder builder) {
148+
return new RestHighLevelClient(builder);
149+
}
150+
151+
}
152+
153+
@Configuration
154+
static class TwoCustomRestHighLevelClientConfiguration {
155+
156+
@Bean
157+
RestHighLevelClient customRestHighLevelClient(RestClientBuilder builder) {
158+
return new RestHighLevelClient(builder);
159+
}
160+
161+
@Bean
162+
RestHighLevelClient customRestHighLevelClient1(RestClientBuilder builder) {
163+
return new RestHighLevelClient(builder);
164+
}
165+
166+
}
167+
109168
}

0 commit comments

Comments
 (0)