diff --git a/src/main/java/org/springframework/data/elasticsearch/core/AbstractElasticsearchTemplate.java b/src/main/java/org/springframework/data/elasticsearch/core/AbstractElasticsearchTemplate.java index c5e48fb1c..f42cd0fec 100644 --- a/src/main/java/org/springframework/data/elasticsearch/core/AbstractElasticsearchTemplate.java +++ b/src/main/java/org/springframework/data/elasticsearch/core/AbstractElasticsearchTemplate.java @@ -101,7 +101,10 @@ protected void initialize(ElasticsearchConverter elasticsearchConverter) { this.routingResolver = new DefaultRoutingResolver((SimpleElasticsearchMappingContext) mappingContext); requestFactory = new RequestFactory(elasticsearchConverter); - VersionInfo.logVersions(getClusterVersion()); + + // initialize the VersionInfo class in the initialization phase + // noinspection ResultOfMethodCallIgnored + VersionInfo.versionProperties(); } /** @@ -166,6 +169,16 @@ public void setRefreshPolicy(@Nullable RefreshPolicy refreshPolicy) { public RefreshPolicy getRefreshPolicy() { return refreshPolicy; } + + /** + * logs the versions of the different Elasticsearch components. + * + * @since 4.3 + */ + public void logVersions() { + VersionInfo.logVersions(getClusterVersion()); + } + // endregion // region DocumentOperations diff --git a/src/main/java/org/springframework/data/elasticsearch/core/DefaultReactiveIndexOperations.java b/src/main/java/org/springframework/data/elasticsearch/core/DefaultReactiveIndexOperations.java index 712df1ef3..d2558113b 100644 --- a/src/main/java/org/springframework/data/elasticsearch/core/DefaultReactiveIndexOperations.java +++ b/src/main/java/org/springframework/data/elasticsearch/core/DefaultReactiveIndexOperations.java @@ -49,8 +49,8 @@ import org.springframework.data.elasticsearch.core.index.DeleteTemplateRequest; import org.springframework.data.elasticsearch.core.index.ExistsTemplateRequest; import org.springframework.data.elasticsearch.core.index.GetTemplateRequest; -import org.springframework.data.elasticsearch.core.index.MappingBuilder; import org.springframework.data.elasticsearch.core.index.PutTemplateRequest; +import org.springframework.data.elasticsearch.core.index.ReactiveMappingBuilder; import org.springframework.data.elasticsearch.core.index.Settings; import org.springframework.data.elasticsearch.core.index.TemplateData; import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentEntity; @@ -190,8 +190,7 @@ public Mono createMapping(Class clazz) { } } - String mapping = new MappingBuilder(converter).buildPropertyMapping(clazz); - return Mono.just(Document.parse(mapping)); + return new ReactiveMappingBuilder(converter).buildReactivePropertyMapping(clazz).map(Document::parse); } @Override diff --git a/src/main/java/org/springframework/data/elasticsearch/core/ReactiveElasticsearchTemplate.java b/src/main/java/org/springframework/data/elasticsearch/core/ReactiveElasticsearchTemplate.java index 67ebf03b8..be256ee3e 100644 --- a/src/main/java/org/springframework/data/elasticsearch/core/ReactiveElasticsearchTemplate.java +++ b/src/main/java/org/springframework/data/elasticsearch/core/ReactiveElasticsearchTemplate.java @@ -142,7 +142,9 @@ public ReactiveElasticsearchTemplate(ReactiveElasticsearchClient client, Elastic this.operations = new EntityOperations(this.mappingContext); this.requestFactory = new RequestFactory(converter); - logVersions(); + // initialize the VersionInfo class in the initialization phase + // noinspection ResultOfMethodCallIgnored + VersionInfo.versionProperties(); } private ReactiveElasticsearchTemplate copy() { @@ -155,11 +157,14 @@ private ReactiveElasticsearchTemplate copy() { return copy; } - private void logVersions() { - getClusterVersion() // - .doOnSuccess(VersionInfo::logVersions) // - .doOnError(e -> VersionInfo.logVersions(null)) // - .subscribe(); + /** + * logs the versions of the different Elasticsearch components. + * + * @return a Mono signalling finished execution + * @since 4.3 + */ + public Mono logVersions() { + return getClusterVersion().doOnNext(VersionInfo::logVersions).then(); } @Override diff --git a/src/main/java/org/springframework/data/elasticsearch/core/ReactiveResourceUtil.java b/src/main/java/org/springframework/data/elasticsearch/core/ReactiveResourceUtil.java index 1598b17fe..168da2f8f 100644 --- a/src/main/java/org/springframework/data/elasticsearch/core/ReactiveResourceUtil.java +++ b/src/main/java/org/springframework/data/elasticsearch/core/ReactiveResourceUtil.java @@ -63,7 +63,7 @@ public static Mono readFileFromClasspath(String url) { String line; while ((line = br.readLine()) != null) { - sb.append(line); + sb.append(line).append('\n'); } sink.next(sb.toString()); diff --git a/src/main/java/org/springframework/data/elasticsearch/core/index/MappingBuilder.java b/src/main/java/org/springframework/data/elasticsearch/core/index/MappingBuilder.java index 1530b1352..a5153bb63 100644 --- a/src/main/java/org/springframework/data/elasticsearch/core/index/MappingBuilder.java +++ b/src/main/java/org/springframework/data/elasticsearch/core/index/MappingBuilder.java @@ -97,7 +97,7 @@ public class MappingBuilder { private static final String DYNAMIC_DATE_FORMATS = "dynamic_date_formats"; private static final String RUNTIME = "runtime"; - private final ElasticsearchConverter elasticsearchConverter; + protected final ElasticsearchConverter elasticsearchConverter; private boolean writeTypeHints = true; @@ -113,9 +113,16 @@ public MappingBuilder(ElasticsearchConverter elasticsearchConverter) { */ public String buildPropertyMapping(Class clazz) throws MappingException { + ElasticsearchPersistentEntity entity = elasticsearchConverter.getMappingContext() + .getRequiredPersistentEntity(clazz); + + return buildPropertyMapping(entity, getRuntimeFields(entity)); + } + + protected String buildPropertyMapping(ElasticsearchPersistentEntity entity, + @Nullable org.springframework.data.elasticsearch.core.document.Document runtimeFields) { + try { - ElasticsearchPersistentEntity entity = elasticsearchConverter.getMappingContext() - .getRequiredPersistentEntity(clazz); writeTypeHints = entity.writeTypeHints(); @@ -124,7 +131,8 @@ public String buildPropertyMapping(Class clazz) throws MappingException { // Dynamic templates addDynamicTemplatesMapping(builder, entity); - mapEntity(builder, entity, true, "", false, FieldType.Auto, null, entity.findAnnotation(DynamicMapping.class)); + mapEntity(builder, entity, true, "", false, FieldType.Auto, null, entity.findAnnotation(DynamicMapping.class), + runtimeFields); builder.endObject() // root object .close(); @@ -148,7 +156,8 @@ private void writeTypeHintMapping(XContentBuilder builder) throws IOException { private void mapEntity(XContentBuilder builder, @Nullable ElasticsearchPersistentEntity entity, boolean isRootObject, String nestedObjectFieldName, boolean nestedOrObjectField, FieldType fieldType, - @Nullable Field parentFieldAnnotation, @Nullable DynamicMapping dynamicMapping) throws IOException { + @Nullable Field parentFieldAnnotation, @Nullable DynamicMapping dynamicMapping, + @Nullable org.springframework.data.elasticsearch.core.document.Document runtimeFields) throws IOException { if (entity != null && entity.isAnnotationPresent(Mapping.class)) { Mapping mappingAnnotation = entity.getRequiredAnnotation(Mapping.class); @@ -170,8 +179,8 @@ private void mapEntity(XContentBuilder builder, @Nullable ElasticsearchPersisten builder.field(DYNAMIC_DATE_FORMATS, mappingAnnotation.dynamicDateFormats()); } - if (StringUtils.hasText(mappingAnnotation.runtimeFieldsPath())) { - addRuntimeFields(builder, mappingAnnotation.runtimeFieldsPath()); + if (runtimeFields != null) { + builder.field(RUNTIME, runtimeFields); } } @@ -227,13 +236,22 @@ private void mapEntity(XContentBuilder builder, @Nullable ElasticsearchPersisten } - private void addRuntimeFields(XContentBuilder builder, String runtimeFieldsPath) throws IOException { + @Nullable + private org.springframework.data.elasticsearch.core.document.Document getRuntimeFields( + @Nullable ElasticsearchPersistentEntity entity) { - ClassPathResource runtimeFields = new ClassPathResource(runtimeFieldsPath); + if (entity != null) { + Mapping mappingAnnotation = entity.findAnnotation(Mapping.class); + if (mappingAnnotation != null) { + String runtimeFieldsPath = mappingAnnotation.runtimeFieldsPath(); - if (runtimeFields.exists()) { - builder.rawField(RUNTIME, runtimeFields.getInputStream(), XContentType.JSON); + if (hasText(runtimeFieldsPath)) { + String jsonString = ResourceUtil.readFileFromClasspath(runtimeFieldsPath); + return org.springframework.data.elasticsearch.core.document.Document.parse(jsonString); + } + } } + return null; } private void buildPropertyMapping(XContentBuilder builder, boolean isRootObject, @@ -291,7 +309,7 @@ private void buildPropertyMapping(XContentBuilder builder, boolean isRootObject, : null; mapEntity(builder, persistentEntity, false, property.getFieldName(), true, fieldAnnotation.type(), - fieldAnnotation, dynamicMapping); + fieldAnnotation, dynamicMapping, null); return; } } diff --git a/src/main/java/org/springframework/data/elasticsearch/core/index/ReactiveMappingBuilder.java b/src/main/java/org/springframework/data/elasticsearch/core/index/ReactiveMappingBuilder.java new file mode 100644 index 000000000..f06b71494 --- /dev/null +++ b/src/main/java/org/springframework/data/elasticsearch/core/index/ReactiveMappingBuilder.java @@ -0,0 +1,78 @@ +/* + * Copyright 2021 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.data.elasticsearch.core.index; + +import static org.springframework.util.StringUtils.*; + +import reactor.core.publisher.Mono; + +import org.springframework.data.elasticsearch.annotations.Mapping; +import org.springframework.data.elasticsearch.core.ReactiveResourceUtil; +import org.springframework.data.elasticsearch.core.convert.ElasticsearchConverter; +import org.springframework.data.elasticsearch.core.document.Document; +import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentEntity; +import org.springframework.data.mapping.MappingException; +import org.springframework.lang.Nullable; + +/** + * Subclass of {@link MappingBuilder} with specialized methods TO inhibit blocking CALLS + * + * @author Peter-Josef Meisch + * @since 4.3 + */ +public class ReactiveMappingBuilder extends MappingBuilder { + + public ReactiveMappingBuilder(ElasticsearchConverter elasticsearchConverter) { + super(elasticsearchConverter); + } + + @Override + public String buildPropertyMapping(Class clazz) throws MappingException { + throw new UnsupportedOperationException( + "Use ReactiveMappingBuilder.buildReactivePropertyMapping() instead of buildPropertyMapping()"); + } + + public Mono buildReactivePropertyMapping(Class clazz) throws MappingException { + ElasticsearchPersistentEntity entity = elasticsearchConverter.getMappingContext() + .getRequiredPersistentEntity(clazz); + + return getRuntimeFields(entity) // + .switchIfEmpty(Mono.just(Document.create())) // + .map(document -> { + if (document.isEmpty()) { + return buildPropertyMapping(entity, null); + } else { + return buildPropertyMapping(entity, document); + } + }); + } + + private Mono getRuntimeFields(@Nullable ElasticsearchPersistentEntity entity) { + + if (entity != null) { + Mapping mappingAnnotation = entity.findAnnotation(Mapping.class); + if (mappingAnnotation != null) { + String runtimeFieldsPath = mappingAnnotation.runtimeFieldsPath(); + + if (hasText(runtimeFieldsPath)) { + return ReactiveResourceUtil.readFileFromClasspath(runtimeFieldsPath).map(Document::parse); + } + } + } + + return Mono.empty(); + } +} diff --git a/src/main/java/org/springframework/data/elasticsearch/support/VersionInfo.java b/src/main/java/org/springframework/data/elasticsearch/support/VersionInfo.java index 43e574398..e7e001bb6 100644 --- a/src/main/java/org/springframework/data/elasticsearch/support/VersionInfo.java +++ b/src/main/java/org/springframework/data/elasticsearch/support/VersionInfo.java @@ -15,9 +15,9 @@ */ package org.springframework.data.elasticsearch.support; +import java.io.IOException; import java.io.InputStream; import java.util.Properties; -import java.util.concurrent.atomic.AtomicBoolean; import org.elasticsearch.Version; import org.slf4j.Logger; @@ -35,70 +35,76 @@ public final class VersionInfo { private static final Logger LOG = LoggerFactory.getLogger(VersionInfo.class); - private static final AtomicBoolean initialized = new AtomicBoolean(false); - private static final String VERSION_PROPERTIES = "versions.properties"; + protected static final String VERSION_PROPERTIES = "versions.properties"; public static final String VERSION_SPRING_DATA_ELASTICSEARCH = "version.spring-data-elasticsearch"; public static final String VERSION_ELASTICSEARCH_CLIENT = "version.elasticsearch-client"; + private static Properties versionProperties; + + public static Properties versionProperties() { + return versionProperties; + } + + static { + try { + versionProperties = loadVersionProperties(); + } catch (IOException e) { + LOG.error("Could not load {}", VERSION_PROPERTIES, e); + versionProperties = new Properties(); + versionProperties.put(VERSION_SPRING_DATA_ELASTICSEARCH, "0.0.0"); + versionProperties.put(VERSION_ELASTICSEARCH_CLIENT, "0.0.0"); + } + } + /** - * logs the relevant version info the first time it is called. Does nothing after the first call - * + * logs the relevant version info. + * * @param clusterVersion the version of the cluster */ public static void logVersions(@Nullable String clusterVersion) { - if (!initialized.getAndSet(true)) { - try { - InputStream resource = VersionInfo.class.getClassLoader().getResourceAsStream(VERSION_PROPERTIES); - if (resource != null) { - Properties properties = new Properties(); - properties.load(resource); - - String versionSpringDataElasticsearch = properties.getProperty(VERSION_SPRING_DATA_ELASTICSEARCH); - Version versionESBuilt = Version.fromString(properties.getProperty(VERSION_ELASTICSEARCH_CLIENT)); - Version versionESUsed = Version.CURRENT; - Version versionESCluster = clusterVersion != null ? Version.fromString(clusterVersion) : null; - - LOG.info("Version Spring Data Elasticsearch: {}", versionSpringDataElasticsearch.toString()); - LOG.info("Version Elasticsearch Client in build: {}", versionESBuilt.toString()); - LOG.info("Version Elasticsearch Client used: {}", versionESUsed.toString()); - - if (differInMajorOrMinor(versionESBuilt, versionESUsed)) { - LOG.warn("Version mismatch in between Elasticsearch Clients build/use: {} - {}", versionESBuilt, - versionESUsed); - } - - if (versionESCluster != null) { - LOG.info("Version Elasticsearch cluster: {}", versionESCluster.toString()); - - if (differInMajorOrMinor(versionESUsed, versionESCluster)) { - LOG.warn("Version mismatch in between Elasticsearch Client and Cluster: {} - {}", versionESUsed, - versionESCluster); - } - } - } else { - LOG.warn("cannot load {}", VERSION_PROPERTIES); - } - } catch (Exception e) { - LOG.warn("Could not log version info: {} - {}", e.getClass().getSimpleName(), e.getMessage()); + try { + + String versionSpringDataElasticsearch = versionProperties.getProperty(VERSION_SPRING_DATA_ELASTICSEARCH); + Version versionESBuilt = Version.fromString(versionProperties.getProperty(VERSION_ELASTICSEARCH_CLIENT)); + Version versionESUsed = Version.CURRENT; + Version versionESCluster = clusterVersion != null ? Version.fromString(clusterVersion) : null; + + LOG.info("Version Spring Data Elasticsearch: {}", versionSpringDataElasticsearch.toString()); + LOG.info("Version Elasticsearch Client in build: {}", versionESBuilt.toString()); + LOG.info("Version Elasticsearch Client used: {}", versionESUsed.toString()); + + if (differInMajorOrMinor(versionESBuilt, versionESUsed)) { + LOG.warn("Version mismatch in between Elasticsearch Clients build/use: {} - {}", versionESBuilt, versionESUsed); } - } - } + if (versionESCluster != null) { + LOG.info("Version Elasticsearch cluster: {}", versionESCluster.toString()); - public static Properties versionProperties() throws Exception { - try { - InputStream resource = VersionInfo.class.getClassLoader().getResourceAsStream(VERSION_PROPERTIES); - if (resource != null) { - Properties properties = new Properties(); - properties.load(resource); - return properties; - } else { - throw new IllegalStateException("Resource not found"); + if (differInMajorOrMinor(versionESUsed, versionESCluster)) { + LOG.warn("Version mismatch in between Elasticsearch Client and Cluster: {} - {}", versionESUsed, + versionESCluster); + } } } catch (Exception e) { - LOG.error("Could not load {}", VERSION_PROPERTIES, e); - throw e; + LOG.warn("Could not log version info: {} - {}", e.getClass().getSimpleName(), e.getMessage()); + } + } + + /** + * gets the version properties from the classpath resource. + * + * @return version properties + * @throws IOException when an error occurs + */ + private static Properties loadVersionProperties() throws IOException { + InputStream resource = VersionInfo.class.getClassLoader().getResourceAsStream(VERSION_PROPERTIES); + if (resource != null) { + Properties properties = new Properties(); + properties.load(resource); + return properties; + } else { + throw new IllegalStateException("Resource not found"); } } diff --git a/src/test/java/org/springframework/data/elasticsearch/blockhound/BlockHoundIntegrationCustomizer.java b/src/test/java/org/springframework/data/elasticsearch/blockhound/BlockHoundIntegrationCustomizer.java index 89a8c6900..17a0c3e5c 100644 --- a/src/test/java/org/springframework/data/elasticsearch/blockhound/BlockHoundIntegrationCustomizer.java +++ b/src/test/java/org/springframework/data/elasticsearch/blockhound/BlockHoundIntegrationCustomizer.java @@ -16,23 +16,26 @@ package org.springframework.data.elasticsearch.blockhound; import reactor.blockhound.BlockHound; +import reactor.blockhound.BlockingOperationError; import reactor.blockhound.integration.BlockHoundIntegration; import org.elasticsearch.Build; import org.elasticsearch.common.xcontent.XContentBuilder; -import org.springframework.data.elasticsearch.support.VersionInfo; /** * @author Peter-Josef Meisch */ public class BlockHoundIntegrationCustomizer implements BlockHoundIntegration { + @Override public void applyTo(BlockHound.Builder builder) { // Elasticsearch classes reading from the classpath on initialization, needed for parsing Elasticsearch responses builder.allowBlockingCallsInside(XContentBuilder.class.getName(), "") .allowBlockingCallsInside(Build.class.getName(), ""); - // Spring Data Elasticsearch classes reading from the classpath - builder.allowBlockingCallsInside(VersionInfo.class.getName(), "logVersions"); + builder.blockingMethodCallback(it -> { + throw new BlockingOperationError(it); + }); + } } diff --git a/src/test/java/org/springframework/data/elasticsearch/core/ReactiveElasticsearchTemplateUnitTests.java b/src/test/java/org/springframework/data/elasticsearch/core/ReactiveElasticsearchTemplateUnitTests.java index ddf2c984a..fcaaa6712 100644 --- a/src/test/java/org/springframework/data/elasticsearch/core/ReactiveElasticsearchTemplateUnitTests.java +++ b/src/test/java/org/springframework/data/elasticsearch/core/ReactiveElasticsearchTemplateUnitTests.java @@ -74,10 +74,6 @@ public class ReactiveElasticsearchTemplateUnitTests { @BeforeEach public void setUp() { - - when(client.info()).thenReturn(Mono.just(new MainResponse("mockNodename", org.elasticsearch.Version.CURRENT, - new ClusterName("mockCluster"), "mockUuid", null))); - template = new ReactiveElasticsearchTemplate(client); } diff --git a/src/test/java/org/springframework/data/elasticsearch/core/index/ReactiveMappingBuilderIntegrationTests.java b/src/test/java/org/springframework/data/elasticsearch/core/index/ReactiveMappingBuilderTests.java similarity index 51% rename from src/test/java/org/springframework/data/elasticsearch/core/index/ReactiveMappingBuilderIntegrationTests.java rename to src/test/java/org/springframework/data/elasticsearch/core/index/ReactiveMappingBuilderTests.java index c163aefef..81833e027 100644 --- a/src/test/java/org/springframework/data/elasticsearch/core/index/ReactiveMappingBuilderIntegrationTests.java +++ b/src/test/java/org/springframework/data/elasticsearch/core/index/ReactiveMappingBuilderTests.java @@ -15,43 +15,67 @@ */ package org.springframework.data.elasticsearch.core.index; +import static org.skyscreamer.jsonassert.JSONAssert.*; import static org.springframework.data.elasticsearch.annotations.FieldType.*; +import reactor.core.publisher.Mono; +import reactor.core.scheduler.Schedulers; + import java.time.Instant; +import org.json.JSONException; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.annotation.Id; import org.springframework.data.elasticsearch.annotations.DateFormat; import org.springframework.data.elasticsearch.annotations.Document; import org.springframework.data.elasticsearch.annotations.Field; import org.springframework.data.elasticsearch.annotations.Mapping; -import org.springframework.data.elasticsearch.core.ReactiveElasticsearchOperations; -import org.springframework.data.elasticsearch.core.ReactiveIndexOperations; -import org.springframework.data.elasticsearch.junit.jupiter.ReactiveElasticsearchRestTemplateConfiguration; -import org.springframework.data.elasticsearch.junit.jupiter.SpringIntegrationTest; +import org.springframework.data.elasticsearch.core.MappingContextBaseTests; import org.springframework.lang.Nullable; -import org.springframework.test.context.ContextConfiguration; /** * @author Peter-Josef Meisch */ -@SpringIntegrationTest -@ContextConfiguration(classes = { ReactiveElasticsearchRestTemplateConfiguration.class }) -public class ReactiveMappingBuilderIntegrationTests { +public class ReactiveMappingBuilderTests extends MappingContextBaseTests { - @Autowired private ReactiveElasticsearchOperations operations; + ReactiveMappingBuilder getReactiveMappingBuilder() { + return new ReactiveMappingBuilder(elasticsearchConverter.get()); + } - @Test // #1822 + @Test // #1822, #1824 @DisplayName("should write runtime fields") - void shouldWriteRuntimeFields() { + void shouldWriteRuntimeFields() throws JSONException { + + ReactiveMappingBuilder mappingBuilder = getReactiveMappingBuilder(); + + String expected = "{\n" + // + " \"runtime\": {\n" + // + " \"day_of_week\": {\n" + // + " \"type\": \"keyword\",\n" + // + " \"script\": {\n" + // + " \"source\": \"emit(doc['@timestamp'].value.dayOfWeekEnum.getDisplayName(TextStyle.FULL, Locale.ROOT))\"\n" + + // + " }\n" + // + " }\n" + // + " },\n" + // + " \"properties\": {\n" + // + " \"_class\": {\n" + // + " \"type\": \"keyword\",\n" + // + " \"index\": false,\n" + // + " \"doc_values\": false\n" + // + " },\n" + // + " \"@timestamp\": {\n" + // + " \"type\": \"date\",\n" + // + " \"format\": \"epoch_millis\"\n" + // + " }\n" + // + " }\n" + // + "}\n"; // - ReactiveIndexOperations indexOps = operations.indexOps(RuntimeFieldEntity.class); + String mapping = Mono.defer(() -> mappingBuilder.buildReactivePropertyMapping(RuntimeFieldEntity.class)) + .subscribeOn(Schedulers.parallel()).block(); - indexOps.create().block(); - indexOps.putMapping().block(); - indexOps.delete().block(); + assertEquals(expected, mapping, true); } // region entities diff --git a/src/test/java/org/springframework/data/elasticsearch/support/VersionInfoTest.java b/src/test/java/org/springframework/data/elasticsearch/support/VersionInfoTest.java new file mode 100644 index 000000000..039372f2e --- /dev/null +++ b/src/test/java/org/springframework/data/elasticsearch/support/VersionInfoTest.java @@ -0,0 +1,41 @@ +/* + * Copyright 2021 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.data.elasticsearch.support; + +import static org.assertj.core.api.Assertions.*; + +import java.io.IOException; +import java.util.Properties; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +/** + * @author Peter-Josef Meisch + */ +class VersionInfoTest { + + @Test // #1824 + @DisplayName("should read version properties") + void shouldReadVersionProperties() throws IOException { + + Properties properties = VersionInfo.versionProperties(); + + assertThat(properties).isNotNull(); + assertThat(properties.getProperty("version.spring-data-elasticsearch")).isNotNull(); + assertThat(properties.getProperty("version.elasticsearch-client")).isNotNull(); + } +}