Skip to content

Commit 2ec61ab

Browse files
authored
DATAES-435 - Report version mismatch if used with older ElasticSearch-version.
Original PR: #413
1 parent 21406a5 commit 2ec61ab

File tree

8 files changed

+181
-5
lines changed

8 files changed

+181
-5
lines changed

Diff for: pom.xml

+17
Original file line numberDiff line numberDiff line change
@@ -292,6 +292,23 @@
292292
</dependencies>
293293

294294
<build>
295+
<resources>
296+
<resource>
297+
<directory>src/main/resources</directory>
298+
<filtering>true</filtering>
299+
<includes>
300+
<include>**/versions.properties</include>
301+
</includes>
302+
</resource>
303+
<resource>
304+
<directory>src/main/resources</directory>
305+
<filtering>false</filtering>
306+
<excludes>
307+
<exclude>**/versions.properties</exclude>
308+
</excludes>
309+
</resource>
310+
</resources>
311+
295312
<plugins>
296313
<!--
297314
please do not remove this configuration for surefire - we need that to avoid issue with jar hell

Diff for: src/main/java/org/springframework/data/elasticsearch/core/AbstractElasticsearchTemplate.java

+16-4
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
import org.springframework.data.elasticsearch.core.query.MoreLikeThisQuery;
3434
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
3535
import org.springframework.data.elasticsearch.core.query.Query;
36+
import org.springframework.data.elasticsearch.support.VersionInfo;
3637
import org.springframework.data.mapping.callback.EntityCallbacks;
3738
import org.springframework.data.util.CloseableIterator;
3839
import org.springframework.data.util.Streamable;
@@ -59,6 +60,8 @@ protected void initialize(ElasticsearchConverter elasticsearchConverter) {
5960

6061
this.elasticsearchConverter = elasticsearchConverter;
6162
requestFactory = new RequestFactory(elasticsearchConverter);
63+
64+
VersionInfo.logVersions(getClusterVersion());
6265
}
6366

6467
protected ElasticsearchConverter createElasticsearchConverter() {
@@ -288,14 +291,14 @@ public <T> SearchHits<T> search(Query query, Class<T> clazz) {
288291
/*
289292
* internal use only, not for public API
290293
*/
291-
abstract protected <T> SearchScrollHits<T> searchScrollStart(long scrollTimeInMillis, Query query,
292-
Class<T> clazz, IndexCoordinates index);
294+
abstract protected <T> SearchScrollHits<T> searchScrollStart(long scrollTimeInMillis, Query query, Class<T> clazz,
295+
IndexCoordinates index);
293296

294297
/*
295298
* internal use only, not for public API
296299
*/
297-
abstract protected <T> SearchScrollHits<T> searchScrollContinue(@Nullable String scrollId,
298-
long scrollTimeInMillis, Class<T> clazz);
300+
abstract protected <T> SearchScrollHits<T> searchScrollContinue(@Nullable String scrollId, long scrollTimeInMillis,
301+
Class<T> clazz);
299302

300303
/*
301304
* internal use only, not for public API
@@ -417,6 +420,15 @@ private <T> IndexQuery getIndexQuery(T entity) {
417420
.withObject(entity) //
418421
.build();
419422
}
423+
424+
/**
425+
* tries to extract the version of the Elasticsearch cluster
426+
*
427+
* @return the version as string if it can be retrieved
428+
*/
429+
@Nullable
430+
abstract protected String getClusterVersion();
431+
420432
// endregion
421433

422434
// region callbacks

Diff for: src/main/java/org/springframework/data/elasticsearch/core/ElasticsearchRestTemplate.java

+12-1
Original file line numberDiff line numberDiff line change
@@ -270,7 +270,8 @@ public <T> SearchScrollHits<T> searchScrollStart(long scrollTimeInMillis, Query
270270
}
271271

272272
@Override
273-
public <T> SearchScrollHits<T> searchScrollContinue(@Nullable String scrollId, long scrollTimeInMillis, Class<T> clazz) {
273+
public <T> SearchScrollHits<T> searchScrollContinue(@Nullable String scrollId, long scrollTimeInMillis,
274+
Class<T> clazz) {
274275

275276
SearchScrollRequest request = new SearchScrollRequest(scrollId);
276277
request.scroll(TimeValue.timeValueMillis(scrollTimeInMillis));
@@ -355,4 +356,14 @@ private RuntimeException translateException(Exception exception) {
355356
}
356357

357358
// endregion
359+
360+
// region helper methods
361+
@Override
362+
protected String getClusterVersion() {
363+
try {
364+
return execute(client -> client.info(RequestOptions.DEFAULT)).getVersion().getNumber();
365+
} catch (Exception ignored) {}
366+
return null;
367+
}
368+
// endregion
358369
}

Diff for: src/main/java/org/springframework/data/elasticsearch/core/ElasticsearchTemplate.java

+22
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,11 @@
1717

1818
import java.util.List;
1919

20+
import org.elasticsearch.Version;
2021
import org.elasticsearch.action.ActionFuture;
22+
import org.elasticsearch.action.admin.cluster.node.info.NodesInfoAction;
23+
import org.elasticsearch.action.admin.cluster.node.info.NodesInfoRequestBuilder;
24+
import org.elasticsearch.action.admin.cluster.node.info.NodesInfoResponse;
2125
import org.elasticsearch.action.bulk.BulkRequestBuilder;
2226
import org.elasticsearch.action.get.GetRequestBuilder;
2327
import org.elasticsearch.action.get.GetResponse;
@@ -320,4 +324,22 @@ private SearchResponse getSearchResponseWithTimeout(ActionFuture<SearchResponse>
320324
return searchTimeout == null ? response.actionGet() : response.actionGet(searchTimeout);
321325
}
322326
// endregion
327+
328+
329+
//region helper methods
330+
@Override
331+
protected String getClusterVersion() {
332+
333+
try {
334+
NodesInfoResponse nodesInfoResponse = client.admin().cluster().nodesInfo(
335+
new NodesInfoRequestBuilder(client, NodesInfoAction.INSTANCE).request()
336+
).actionGet();
337+
if (!nodesInfoResponse.getNodes().isEmpty()) {
338+
return nodesInfoResponse.getNodes().get(0).getVersion().toString();
339+
}
340+
} catch (Exception ignored) {
341+
}
342+
return null;
343+
}
344+
//endregion
323345
}

Diff for: src/main/java/org/springframework/data/elasticsearch/core/ReactiveElasticsearchTemplate.java

+20
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@
8282
import org.springframework.data.elasticsearch.core.query.Query;
8383
import org.springframework.data.elasticsearch.core.query.StringQuery;
8484
import org.springframework.data.elasticsearch.core.query.UpdateQuery;
85+
import org.springframework.data.elasticsearch.support.VersionInfo;
8586
import org.springframework.data.mapping.callback.ReactiveEntityCallbacks;
8687
import org.springframework.data.mapping.context.MappingContext;
8788
import org.springframework.http.HttpStatus;
@@ -131,6 +132,15 @@ public ReactiveElasticsearchTemplate(ReactiveElasticsearchClient client, Elastic
131132
this.exceptionTranslator = new ElasticsearchExceptionTranslator();
132133
this.operations = new EntityOperations(this.mappingContext);
133134
this.requestFactory = new RequestFactory(converter);
135+
136+
logVersions();
137+
}
138+
139+
private void logVersions() {
140+
getClusterVersion() //
141+
.doOnSuccess(VersionInfo::logVersions) //
142+
.doOnError(e -> VersionInfo.logVersions(null)) //
143+
.subscribe();
134144
}
135145

136146
@Override
@@ -157,6 +167,7 @@ public void setEntityCallbacks(ReactiveEntityCallbacks entityCallbacks) {
157167

158168
this.entityCallbacks = entityCallbacks;
159169
}
170+
160171
// endregion
161172

162173
// region DocumentOperations
@@ -775,6 +786,15 @@ protected SearchRequest prepareSearchRequest(SearchRequest request) {
775786
// endregion
776787

777788
// region Helper methods
789+
protected Mono<String> getClusterVersion() {
790+
try {
791+
return Mono.from(execute(client -> client.info())).map(mainResponse -> mainResponse.getVersion().toString());
792+
} catch (Exception ignored) {}
793+
return Mono.empty();
794+
}
795+
796+
// endregion
797+
778798
// Property Setters / Getters
779799

780800
/**
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
/*
2+
* Copyright 2020 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+
package org.springframework.data.elasticsearch.support;
17+
18+
import java.io.InputStream;
19+
import java.util.Properties;
20+
import java.util.concurrent.atomic.AtomicBoolean;
21+
22+
import org.elasticsearch.Version;
23+
import org.slf4j.Logger;
24+
import org.slf4j.LoggerFactory;
25+
import org.springframework.lang.Nullable;
26+
27+
/**
28+
* This class is used to log the versions of Spring Data Elasticsearch, the Elasticsearch client libs used to built, the
29+
* Elasticsearch client libs currently used and of the Elasticsearch cluster. If differences greater than a patchlevel
30+
* are detected, these are logged as warnings.
31+
*
32+
* @author Peter-Josef Meisch
33+
* @since 4.0
34+
*/
35+
public final class VersionInfo {
36+
37+
private static final Logger LOG = LoggerFactory.getLogger(VersionInfo.class);
38+
private static final AtomicBoolean initialized = new AtomicBoolean(false);
39+
private static String VERSION_PROPERTIES = "versions.properties";
40+
41+
/**
42+
* logs the relevant version info the first time it is called. Does nothing after the first call
43+
*
44+
* @param clusterVersion the version of the cluster
45+
*/
46+
public static void logVersions(@Nullable String clusterVersion) {
47+
if (!initialized.getAndSet(true)) {
48+
try {
49+
InputStream resource = VersionInfo.class.getClassLoader().getResourceAsStream(VERSION_PROPERTIES);
50+
if (resource != null) {
51+
Properties properties = new Properties();
52+
properties.load(resource);
53+
54+
String versionSpringDataElasticsearch = properties.getProperty("version.spring-data-elasticsearch");
55+
Version versionESBuilt = Version.fromString(properties.getProperty("version.elasticsearch-client"));
56+
Version versionESUsed = Version.CURRENT;
57+
Version versionESCluster = clusterVersion != null ? Version.fromString(clusterVersion) : null;
58+
59+
LOG.info("Version Spring Data Elasticsearch: {}", versionSpringDataElasticsearch.toString());
60+
LOG.info("Version Elasticsearch Client in build: {}", versionESBuilt.toString());
61+
LOG.info("Version Elasticsearch Client used: {}", versionESUsed.toString());
62+
63+
if (differInMajorOrMinor(versionESBuilt, versionESUsed)) {
64+
LOG.warn("Version mismatch in between Elasticsearch Clients build/use: {} - {}", versionESBuilt,
65+
versionESUsed);
66+
}
67+
68+
if (versionESCluster != null) {
69+
LOG.info("Version Elasticsearch cluster: {}", versionESCluster.toString());
70+
71+
if (differInMajorOrMinor(versionESUsed, versionESCluster)) {
72+
LOG.warn("Version mismatch in between Elasticsearch Client and Cluster: {} - {}", versionESUsed,
73+
versionESCluster);
74+
}
75+
}
76+
} else {
77+
LOG.warn("cannot load {}", VERSION_PROPERTIES);
78+
}
79+
} catch (Exception e) {
80+
LOG.warn("Could not log version info: {} - {}", e.getClass().getSimpleName(), e.getMessage());
81+
}
82+
83+
}
84+
}
85+
86+
private static boolean differInMajorOrMinor(Version version1, Version version2) {
87+
return version1.major != version2.major || version1.minor != version2.minor;
88+
}
89+
90+
private VersionInfo() {}
91+
}

Diff for: src/main/resources/versions.properties

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
version.spring-data-elasticsearch=${project.version}
2+
version.elasticsearch-client=${elasticsearch}

Diff for: src/test/resources/logback.xml

+1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
</encoder>
88
</appender>
99

10+
<logger name="org.springframework.data.elasticsearch.support.VersionInfo" level="info"/>
1011
<logger name="org.springframework.data.elasticsearch.junit" level="debug"/>
1112
<logger name="org.springframework.data.elasticsearch.junit.junit4.ElasticsearchVersionRule" level="info"/>
1213
<logger name="org.springframework.data.elasticsearch.client.WIRE" level="info"/>

0 commit comments

Comments
 (0)