Browse Source
Prior to this commit, Spring Boot would auto-configure both
Elasticsearch variants: `RestClient` ("Low Level" client) and
`RestHighLevelClient` ("High Level" client).
Since one can be derived from the other, this would create complex and
unclear situations depending on what developers provided with their
configuration.
`RestHighLevelClient` is mostly for actual use of the Elasticsearch API,
with support for specific methods and (de)serialization. On the other
hand, `RestClient` is merely wrapping the Apache HTTP client for
load-balancing support and low level HTTP features.
This commit completely removes the support for `RestClient` in Spring
Boot and now requires the presence of the
`org.elasticsearch.client:elasticsearch-rest-high-level-client`
dependency for REST client support with Elasticsearch.
Closes gh-22358
pull/23219/head
6 changed files with 191 additions and 281 deletions
@ -1,208 +0,0 @@
@@ -1,208 +0,0 @@
|
||||
/* |
||||
* Copyright 2012-2020 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.autoconfigure.elasticsearch; |
||||
|
||||
import java.net.URI; |
||||
import java.net.URISyntaxException; |
||||
import java.time.Duration; |
||||
|
||||
import org.apache.http.HttpHost; |
||||
import org.apache.http.auth.AuthScope; |
||||
import org.apache.http.auth.Credentials; |
||||
import org.apache.http.auth.UsernamePasswordCredentials; |
||||
import org.apache.http.client.config.RequestConfig; |
||||
import org.apache.http.impl.client.BasicCredentialsProvider; |
||||
import org.apache.http.impl.nio.client.HttpAsyncClientBuilder; |
||||
import org.elasticsearch.client.RestClient; |
||||
import org.elasticsearch.client.RestClientBuilder; |
||||
import org.elasticsearch.client.RestHighLevelClient; |
||||
|
||||
import org.springframework.beans.factory.ObjectProvider; |
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; |
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; |
||||
import org.springframework.boot.context.properties.PropertyMapper; |
||||
import org.springframework.context.annotation.Bean; |
||||
import org.springframework.context.annotation.Configuration; |
||||
import org.springframework.util.StringUtils; |
||||
|
||||
/** |
||||
* Elasticsearch rest client infrastructure configurations. |
||||
* |
||||
* @author Brian Clozel |
||||
* @author Stephane Nicoll |
||||
* @author Vedran Pavic |
||||
* @author Evgeniy Cheban |
||||
*/ |
||||
class ElasticsearchRestClientConfigurations { |
||||
|
||||
@Configuration(proxyBeanMethods = false) |
||||
@ConditionalOnMissingBean(RestClientBuilder.class) |
||||
static class RestClientBuilderConfiguration { |
||||
|
||||
@Bean |
||||
RestClientBuilderCustomizer defaultRestClientBuilderCustomizer(ElasticsearchRestClientProperties properties) { |
||||
return new DefaultRestClientBuilderCustomizer(properties); |
||||
} |
||||
|
||||
@Bean |
||||
RestClientBuilder elasticsearchRestClientBuilder(ElasticsearchRestClientProperties properties, |
||||
ObjectProvider<RestClientBuilderCustomizer> builderCustomizers) { |
||||
HttpHost[] hosts = properties.getUris().stream().map(this::createHttpHost).toArray(HttpHost[]::new); |
||||
RestClientBuilder builder = RestClient.builder(hosts); |
||||
builder.setHttpClientConfigCallback((httpClientBuilder) -> { |
||||
builderCustomizers.orderedStream().forEach((customizer) -> customizer.customize(httpClientBuilder)); |
||||
return httpClientBuilder; |
||||
}); |
||||
builder.setRequestConfigCallback((requestConfigBuilder) -> { |
||||
builderCustomizers.orderedStream().forEach((customizer) -> customizer.customize(requestConfigBuilder)); |
||||
return requestConfigBuilder; |
||||
}); |
||||
builderCustomizers.orderedStream().forEach((customizer) -> customizer.customize(builder)); |
||||
return builder; |
||||
} |
||||
|
||||
private HttpHost createHttpHost(String uri) { |
||||
try { |
||||
return createHttpHost(URI.create(uri)); |
||||
} |
||||
catch (IllegalArgumentException ex) { |
||||
return HttpHost.create(uri); |
||||
} |
||||
} |
||||
|
||||
private HttpHost createHttpHost(URI uri) { |
||||
if (!StringUtils.hasLength(uri.getUserInfo())) { |
||||
return HttpHost.create(uri.toString()); |
||||
} |
||||
try { |
||||
return HttpHost.create(new URI(uri.getScheme(), null, uri.getHost(), uri.getPort(), uri.getPath(), |
||||
uri.getQuery(), uri.getFragment()).toString()); |
||||
} |
||||
catch (URISyntaxException ex) { |
||||
throw new IllegalStateException(ex); |
||||
} |
||||
} |
||||
|
||||
} |
||||
|
||||
@Configuration(proxyBeanMethods = false) |
||||
@ConditionalOnClass(RestHighLevelClient.class) |
||||
static class RestHighLevelClientConfiguration { |
||||
|
||||
@Bean |
||||
@ConditionalOnMissingBean |
||||
RestHighLevelClient elasticsearchRestHighLevelClient(RestClientBuilder restClientBuilder) { |
||||
return new RestHighLevelClient(restClientBuilder); |
||||
} |
||||
|
||||
@Bean |
||||
@ConditionalOnMissingBean |
||||
RestClient elasticsearchRestClient(RestClientBuilder builder, |
||||
ObjectProvider<RestHighLevelClient> restHighLevelClient) { |
||||
RestHighLevelClient client = restHighLevelClient.getIfUnique(); |
||||
if (client != null) { |
||||
return client.getLowLevelClient(); |
||||
} |
||||
return builder.build(); |
||||
} |
||||
|
||||
} |
||||
|
||||
@Configuration(proxyBeanMethods = false) |
||||
static class RestClientFallbackConfiguration { |
||||
|
||||
@Bean |
||||
@ConditionalOnMissingBean |
||||
RestClient elasticsearchRestClient(RestClientBuilder builder) { |
||||
return builder.build(); |
||||
} |
||||
|
||||
} |
||||
|
||||
static class DefaultRestClientBuilderCustomizer implements RestClientBuilderCustomizer { |
||||
|
||||
private static final PropertyMapper map = PropertyMapper.get(); |
||||
|
||||
private final ElasticsearchRestClientProperties properties; |
||||
|
||||
DefaultRestClientBuilderCustomizer(ElasticsearchRestClientProperties properties) { |
||||
this.properties = properties; |
||||
} |
||||
|
||||
@Override |
||||
public void customize(RestClientBuilder builder) { |
||||
} |
||||
|
||||
@Override |
||||
public void customize(HttpAsyncClientBuilder builder) { |
||||
builder.setDefaultCredentialsProvider(new PropertiesCredentialsProvider(this.properties)); |
||||
} |
||||
|
||||
@Override |
||||
public void customize(RequestConfig.Builder builder) { |
||||
map.from(this.properties::getConnectionTimeout).whenNonNull().asInt(Duration::toMillis) |
||||
.to(builder::setConnectTimeout); |
||||
map.from(this.properties::getReadTimeout).whenNonNull().asInt(Duration::toMillis) |
||||
.to(builder::setSocketTimeout); |
||||
} |
||||
|
||||
} |
||||
|
||||
private static class PropertiesCredentialsProvider extends BasicCredentialsProvider { |
||||
|
||||
PropertiesCredentialsProvider(ElasticsearchRestClientProperties properties) { |
||||
if (StringUtils.hasText(properties.getUsername())) { |
||||
Credentials credentials = new UsernamePasswordCredentials(properties.getUsername(), |
||||
properties.getPassword()); |
||||
setCredentials(AuthScope.ANY, credentials); |
||||
} |
||||
properties.getUris().stream().map(this::toUri).filter(this::hasUserInfo) |
||||
.forEach(this::addUserInfoCredentials); |
||||
} |
||||
|
||||
private URI toUri(String uri) { |
||||
try { |
||||
return URI.create(uri); |
||||
} |
||||
catch (IllegalArgumentException ex) { |
||||
return null; |
||||
} |
||||
} |
||||
|
||||
private boolean hasUserInfo(URI uri) { |
||||
return uri != null && StringUtils.hasLength(uri.getUserInfo()); |
||||
} |
||||
|
||||
private void addUserInfoCredentials(URI uri) { |
||||
AuthScope authScope = new AuthScope(uri.getHost(), uri.getPort()); |
||||
Credentials credentials = createUserInfoCredentials(uri.getUserInfo()); |
||||
setCredentials(authScope, credentials); |
||||
} |
||||
|
||||
private Credentials createUserInfoCredentials(String userInfo) { |
||||
int delimiter = userInfo.indexOf(":"); |
||||
if (delimiter == -1) { |
||||
return new UsernamePasswordCredentials(userInfo, null); |
||||
} |
||||
String username = userInfo.substring(0, delimiter); |
||||
String password = userInfo.substring(delimiter + 1); |
||||
return new UsernamePasswordCredentials(username, password); |
||||
} |
||||
|
||||
} |
||||
|
||||
} |
||||
Loading…
Reference in new issue