DATAES-914 - Use TestContainers.
This commit is contained in:
@@ -1,49 +0,0 @@
|
||||
/*
|
||||
* Copyright 2019-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.data.elasticsearch;
|
||||
|
||||
import org.elasticsearch.client.Client;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.elasticsearch.config.ElasticsearchConfigurationSupport;
|
||||
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
|
||||
import org.springframework.data.elasticsearch.core.convert.ElasticsearchConverter;
|
||||
import org.springframework.data.elasticsearch.junit.junit4.TestNodeResource;
|
||||
|
||||
/**
|
||||
* configuration class for the classic ElasticsearchTemplate. Needs a {@link TestNodeResource} bean that should be set
|
||||
* up in the test as ClassRule and exported as bean.
|
||||
*
|
||||
* @author Peter-Josef Meisch
|
||||
*/
|
||||
@Configuration
|
||||
public class ElasticsearchTestConfiguration extends ElasticsearchConfigurationSupport {
|
||||
|
||||
@Autowired private TestNodeResource testNodeResource;
|
||||
|
||||
@Bean
|
||||
public Client elasticsearchClient() {
|
||||
return testNodeResource.client();
|
||||
}
|
||||
|
||||
@Bean(name = { "elasticsearchOperations", "elasticsearchTemplate" })
|
||||
public ElasticsearchTemplate elasticsearchTemplate(Client elasticsearchClient,
|
||||
ElasticsearchConverter elasticsearchConverter) {
|
||||
return new ElasticsearchTemplate(elasticsearchClient, elasticsearchConverter);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
/*
|
||||
* Copyright 2019-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.data.elasticsearch;
|
||||
|
||||
import org.elasticsearch.client.RestHighLevelClient;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.elasticsearch.config.AbstractElasticsearchConfiguration;
|
||||
|
||||
/**
|
||||
* @author Peter-Josef Meisch
|
||||
*/
|
||||
@Configuration
|
||||
public class RestElasticsearchTestConfiguration extends AbstractElasticsearchConfiguration {
|
||||
|
||||
@Override
|
||||
@Bean
|
||||
public RestHighLevelClient elasticsearchClient() {
|
||||
return TestUtils.restHighLevelClient();
|
||||
}
|
||||
}
|
||||
@@ -1,137 +0,0 @@
|
||||
/*
|
||||
* Copyright 2018-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.data.elasticsearch;
|
||||
|
||||
import lombok.SneakyThrows;
|
||||
|
||||
import java.time.Duration;
|
||||
|
||||
import org.elasticsearch.ElasticsearchStatusException;
|
||||
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
|
||||
import org.elasticsearch.action.get.GetRequest;
|
||||
import org.elasticsearch.action.search.SearchRequest;
|
||||
import org.elasticsearch.client.RequestOptions;
|
||||
import org.elasticsearch.client.RestHighLevelClient;
|
||||
import org.elasticsearch.index.query.QueryBuilders;
|
||||
import org.elasticsearch.search.builder.SearchSourceBuilder;
|
||||
import org.springframework.data.elasticsearch.client.ClientConfiguration;
|
||||
import org.springframework.data.elasticsearch.client.RestClients;
|
||||
import org.springframework.data.elasticsearch.client.reactive.ReactiveElasticsearchClient;
|
||||
import org.springframework.data.elasticsearch.client.reactive.ReactiveRestClients;
|
||||
import org.springframework.data.elasticsearch.support.SearchHitsUtil;
|
||||
import org.springframework.data.util.Version;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
/**
|
||||
* @author Christoph Strobl
|
||||
* @author Mark Paluch
|
||||
* @currentRead Fool's Fate - Robin Hobb
|
||||
*/
|
||||
public final class TestUtils {
|
||||
|
||||
private TestUtils() {}
|
||||
|
||||
private static final ClientConfiguration CONFIG = ClientConfiguration.builder().connectedToLocalhost()
|
||||
.withConnectTimeout(Duration.ofSeconds(5)).withSocketTimeout(Duration.ofSeconds(3)).build();
|
||||
|
||||
public static RestHighLevelClient restHighLevelClient() {
|
||||
return RestClients.create(CONFIG).rest();
|
||||
}
|
||||
|
||||
public static ReactiveElasticsearchClient reactiveClient() {
|
||||
return ReactiveRestClients.create(CONFIG);
|
||||
}
|
||||
|
||||
public static Version serverVersion() {
|
||||
|
||||
try (RestHighLevelClient client = restHighLevelClient()) {
|
||||
|
||||
org.elasticsearch.Version version = org.elasticsearch.Version
|
||||
.fromString(client.info(RequestOptions.DEFAULT).getVersion().getNumber());
|
||||
return new Version(version.major, version.minor, version.revision);
|
||||
|
||||
} catch (Exception e) {
|
||||
return new Version(0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@SneakyThrows
|
||||
public static void deleteIndex(String... indexes) {
|
||||
|
||||
if (ObjectUtils.isEmpty(indexes)) {
|
||||
return;
|
||||
}
|
||||
|
||||
try (RestHighLevelClient client = restHighLevelClient()) {
|
||||
for (String index : indexes) {
|
||||
|
||||
try {
|
||||
client.indices().delete(new DeleteIndexRequest(index), RequestOptions.DEFAULT);
|
||||
} catch (ElasticsearchStatusException ex) {
|
||||
// just ignore it
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SneakyThrows
|
||||
public static boolean isEmptyIndex(String indexName) {
|
||||
|
||||
try (RestHighLevelClient client = restHighLevelClient()) {
|
||||
|
||||
return 0L == SearchHitsUtil.getTotalCount(client
|
||||
.search(new SearchRequest(indexName)
|
||||
.source(SearchSourceBuilder.searchSource().query(QueryBuilders.matchAllQuery())), RequestOptions.DEFAULT)
|
||||
.getHits());
|
||||
}
|
||||
}
|
||||
|
||||
public static OfType documentWithId(String id) {
|
||||
return new DocumentLookup(id);
|
||||
}
|
||||
|
||||
public interface ExistsIn {
|
||||
boolean existsIn(String index);
|
||||
}
|
||||
|
||||
public interface OfType extends ExistsIn {
|
||||
ExistsIn ofType(String type);
|
||||
}
|
||||
|
||||
private static class DocumentLookup implements OfType {
|
||||
|
||||
private String id;
|
||||
|
||||
public DocumentLookup(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SneakyThrows
|
||||
public boolean existsIn(String index) {
|
||||
|
||||
GetRequest request = new GetRequest(index).id(id);
|
||||
try (RestHighLevelClient client = restHighLevelClient()) {
|
||||
return client.get(request, RequestOptions.DEFAULT).isExists();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExistsIn ofType(String type) {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,64 +0,0 @@
|
||||
/*
|
||||
* Copyright 2015-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.data.elasticsearch;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.elasticsearch.client.Client;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.join.ParentJoinPlugin;
|
||||
import org.elasticsearch.node.Node;
|
||||
import org.elasticsearch.node.NodeValidationException;
|
||||
import org.elasticsearch.transport.Netty4Plugin;
|
||||
import org.springframework.data.elasticsearch.client.NodeClientFactoryBean;
|
||||
|
||||
/**
|
||||
* @author Mohsin Husen
|
||||
* @author Artur Konczak
|
||||
* @author Ilkang Na
|
||||
* @author Peter-Josef Meisch
|
||||
* @author Roman Puchkovskiy
|
||||
* @author Subhobrata Dey
|
||||
*/
|
||||
public class Utils {
|
||||
|
||||
public static Node getNode() {
|
||||
String pathHome = "src/test/resources/test-home-dir";
|
||||
String pathData = "target/elasticsearchTestData";
|
||||
String clusterName = UUID.randomUUID().toString();
|
||||
|
||||
return new NodeClientFactoryBean.TestNode( //
|
||||
Settings.builder() //
|
||||
.put("transport.type", "netty4") //
|
||||
.put("http.type", "netty4") //
|
||||
.put("path.home", pathHome) //
|
||||
.put("path.data", pathData) //
|
||||
.put("cluster.name", clusterName) //
|
||||
.put("node.max_local_storage_nodes", 100)//
|
||||
// the following 3 settings are needed to avoid problems on big, but
|
||||
// almost full filesystems, see DATAES-741
|
||||
.put("cluster.routing.allocation.disk.watermark.low", "1gb")//
|
||||
.put("cluster.routing.allocation.disk.watermark.high", "1gb")//
|
||||
.put("cluster.routing.allocation.disk.watermark.flood_stage", "1gb")//
|
||||
.build(), //
|
||||
Arrays.asList(Netty4Plugin.class, ParentJoinPlugin.class));
|
||||
}
|
||||
|
||||
public static Client getNodeClient() throws NodeValidationException {
|
||||
return getNode().start().client();
|
||||
}
|
||||
}
|
||||
@@ -18,9 +18,9 @@ package org.springframework.data.elasticsearch.client.reactive;
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
|
||||
import lombok.SneakyThrows;
|
||||
import reactor.core.publisher.Mono;
|
||||
import reactor.test.StepVerifier;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.time.Duration;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
@@ -39,11 +39,6 @@ import org.elasticsearch.action.index.IndexRequest;
|
||||
import org.elasticsearch.action.search.SearchRequest;
|
||||
import org.elasticsearch.action.support.WriteRequest.RefreshPolicy;
|
||||
import org.elasticsearch.action.update.UpdateRequest;
|
||||
import org.elasticsearch.client.RequestOptions;
|
||||
import org.elasticsearch.client.RestHighLevelClient;
|
||||
import org.elasticsearch.client.indices.CreateIndexRequest;
|
||||
import org.elasticsearch.client.indices.GetIndexRequest;
|
||||
import org.elasticsearch.client.indices.PutMappingRequest;
|
||||
import org.elasticsearch.common.unit.TimeValue;
|
||||
import org.elasticsearch.index.get.GetResult;
|
||||
import org.elasticsearch.index.query.QueryBuilders;
|
||||
@@ -58,13 +53,17 @@ import org.elasticsearch.search.suggest.completion.CompletionSuggestionBuilder;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.data.elasticsearch.TestUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.elasticsearch.client.ClientConfiguration;
|
||||
import org.springframework.data.elasticsearch.junit.junit4.ElasticsearchVersion;
|
||||
import org.springframework.data.elasticsearch.junit.jupiter.ElasticsearchRestTemplateConfiguration;
|
||||
import org.springframework.data.elasticsearch.core.ReactiveElasticsearchOperations;
|
||||
import org.springframework.data.elasticsearch.core.ReactiveIndexOperations;
|
||||
import org.springframework.data.elasticsearch.core.document.Document;
|
||||
import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates;
|
||||
import org.springframework.data.elasticsearch.junit.jupiter.ReactiveElasticsearchRestTemplateConfiguration;
|
||||
import org.springframework.data.elasticsearch.junit.jupiter.SpringIntegrationTest;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
|
||||
/**
|
||||
@@ -76,21 +75,27 @@ import org.springframework.test.context.ContextConfiguration;
|
||||
* @author Thomas Geese
|
||||
*/
|
||||
@SpringIntegrationTest
|
||||
@ContextConfiguration(classes = { ElasticsearchRestTemplateConfiguration.class })
|
||||
@ContextConfiguration(classes = { ReactiveElasticsearchClientTests.Config.class })
|
||||
public class ReactiveElasticsearchClientTests {
|
||||
|
||||
@Configuration
|
||||
static class Config extends ReactiveElasticsearchRestTemplateConfiguration {
|
||||
@Override
|
||||
@Bean
|
||||
public ReactiveElasticsearchClient reactiveElasticsearchClient() {
|
||||
return super.reactiveElasticsearchClient();
|
||||
}
|
||||
}
|
||||
|
||||
static final String INDEX_I = "idx-1-reactive-client-tests";
|
||||
static final String INDEX_II = "idx-2-reactive-client-tests";
|
||||
|
||||
static final String TYPE_I = "doc-type-1";
|
||||
static final String TYPE_II = "doc-type-2";
|
||||
|
||||
// must be <String, Object> and not <String, String>, otherwise UpdateRequest.doc() will use the overload with
|
||||
// (Object...)
|
||||
static final Map<String, Object> DOC_SOURCE;
|
||||
|
||||
RestHighLevelClient syncClient;
|
||||
ReactiveElasticsearchClient client;
|
||||
@Autowired ReactiveElasticsearchClient client;
|
||||
@Autowired ReactiveElasticsearchOperations operations;
|
||||
|
||||
static {
|
||||
|
||||
@@ -103,19 +108,14 @@ public class ReactiveElasticsearchClientTests {
|
||||
|
||||
@BeforeEach
|
||||
public void setUp() {
|
||||
|
||||
syncClient = TestUtils.restHighLevelClient();
|
||||
client = TestUtils.reactiveClient();
|
||||
|
||||
TestUtils.deleteIndex(INDEX_I, INDEX_II);
|
||||
operations.indexOps(IndexCoordinates.of(INDEX_I)).delete().block();
|
||||
operations.indexOps(IndexCoordinates.of(INDEX_II)).delete().block();
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
public void after() throws IOException {
|
||||
|
||||
TestUtils.deleteIndex(INDEX_I, INDEX_II);
|
||||
|
||||
syncClient.close();
|
||||
public void after() {
|
||||
operations.indexOps(IndexCoordinates.of(INDEX_I)).delete().block();
|
||||
operations.indexOps(IndexCoordinates.of(INDEX_II)).delete().block();
|
||||
}
|
||||
|
||||
@Test // DATAES-488
|
||||
@@ -157,7 +157,7 @@ public class ReactiveElasticsearchClientTests {
|
||||
@Test // DATAES-488
|
||||
public void getShouldFetchDocumentById() {
|
||||
|
||||
String id = addSourceDocument().ofType(TYPE_I).to(INDEX_I);
|
||||
String id = addSourceDocument().to(INDEX_I);
|
||||
|
||||
client.get(new GetRequest(INDEX_I, id)) //
|
||||
.as(StepVerifier::create) //
|
||||
@@ -172,7 +172,7 @@ public class ReactiveElasticsearchClientTests {
|
||||
@Test // DATAES-488
|
||||
public void getShouldCompleteForNonExistingDocuments() {
|
||||
|
||||
addSourceDocument().ofType(TYPE_I).to(INDEX_I);
|
||||
addSourceDocument().to(INDEX_I);
|
||||
|
||||
String id = "this-one-does-not-exist";
|
||||
client.get(new GetRequest(INDEX_I, id)) //
|
||||
@@ -183,8 +183,8 @@ public class ReactiveElasticsearchClientTests {
|
||||
@Test // DATAES-488
|
||||
public void multiGetShouldReturnAllDocumentsFromSameCollection() {
|
||||
|
||||
String id1 = addSourceDocument().ofType(TYPE_I).to(INDEX_I);
|
||||
String id2 = addSourceDocument().ofType(TYPE_I).to(INDEX_I);
|
||||
String id1 = addSourceDocument().to(INDEX_I);
|
||||
String id2 = addSourceDocument().to(INDEX_I);
|
||||
|
||||
MultiGetRequest request = new MultiGetRequest() //
|
||||
.add(INDEX_I, id1) //
|
||||
@@ -200,8 +200,8 @@ public class ReactiveElasticsearchClientTests {
|
||||
@Test // DATAES-488
|
||||
public void multiGetShouldReturnAllExistingDocumentsFromSameCollection() {
|
||||
|
||||
String id1 = addSourceDocument().ofType(TYPE_I).to(INDEX_I);
|
||||
addSourceDocument().ofType(TYPE_I).to(INDEX_I);
|
||||
String id1 = addSourceDocument().to(INDEX_I);
|
||||
addSourceDocument().to(INDEX_I);
|
||||
|
||||
MultiGetRequest request = new MultiGetRequest() //
|
||||
.add(INDEX_I, id1) //
|
||||
@@ -216,8 +216,8 @@ public class ReactiveElasticsearchClientTests {
|
||||
@Test // DATAES-488
|
||||
public void multiGetShouldSkipNonExistingDocuments() {
|
||||
|
||||
String id1 = addSourceDocument().ofType(TYPE_I).to(INDEX_I);
|
||||
String id2 = addSourceDocument().ofType(TYPE_I).to(INDEX_I);
|
||||
String id1 = addSourceDocument().to(INDEX_I);
|
||||
String id2 = addSourceDocument().to(INDEX_I);
|
||||
|
||||
MultiGetRequest request = new MultiGetRequest() //
|
||||
.add(INDEX_I, id1) //
|
||||
@@ -234,8 +234,8 @@ public class ReactiveElasticsearchClientTests {
|
||||
@Test // DATAES-488
|
||||
public void multiGetShouldCompleteIfNothingFound() {
|
||||
|
||||
String id1 = addSourceDocument().ofType(TYPE_I).to(INDEX_I);
|
||||
String id2 = addSourceDocument().ofType(TYPE_I).to(INDEX_I);
|
||||
String id1 = addSourceDocument().to(INDEX_I);
|
||||
String id2 = addSourceDocument().to(INDEX_I);
|
||||
|
||||
client.multiGet(new MultiGetRequest() //
|
||||
.add(INDEX_II, id1).add(INDEX_II, id2)) //
|
||||
@@ -246,8 +246,8 @@ public class ReactiveElasticsearchClientTests {
|
||||
@Test // DATAES-488
|
||||
public void multiGetShouldReturnAllExistingDocumentsFromDifferentCollection() {
|
||||
|
||||
String id1 = addSourceDocument().ofType(TYPE_I).to(INDEX_I);
|
||||
String id2 = addSourceDocument().ofType(TYPE_II).to(INDEX_II);
|
||||
String id1 = addSourceDocument().to(INDEX_I);
|
||||
String id2 = addSourceDocument().to(INDEX_II);
|
||||
|
||||
MultiGetRequest request = new MultiGetRequest() //
|
||||
.add(INDEX_I, id1) //
|
||||
@@ -263,7 +263,7 @@ public class ReactiveElasticsearchClientTests {
|
||||
@Test // DATAES-488
|
||||
public void existsReturnsTrueForExistingDocuments() {
|
||||
|
||||
String id = addSourceDocument().ofType(TYPE_I).to(INDEX_I);
|
||||
String id = addSourceDocument().to(INDEX_I);
|
||||
|
||||
client.exists(new GetRequest(INDEX_I, id)) //
|
||||
.as(StepVerifier::create) //
|
||||
@@ -274,7 +274,7 @@ public class ReactiveElasticsearchClientTests {
|
||||
@Test // DATAES-488
|
||||
public void existsReturnsFalseForNonExistingDocuments() {
|
||||
|
||||
String id = addSourceDocument().ofType(TYPE_I).to(INDEX_I);
|
||||
String id = addSourceDocument().to(INDEX_I);
|
||||
|
||||
client.exists(new GetRequest(INDEX_II, id)) //
|
||||
.as(StepVerifier::create) //
|
||||
@@ -285,7 +285,7 @@ public class ReactiveElasticsearchClientTests {
|
||||
@Test // DATAES-488
|
||||
public void indexShouldAddDocument() {
|
||||
|
||||
IndexRequest request = indexRequest(DOC_SOURCE, INDEX_I, TYPE_I);
|
||||
IndexRequest request = indexRequest();
|
||||
|
||||
client.index(request) //
|
||||
.as(StepVerifier::create) //
|
||||
@@ -300,9 +300,9 @@ public class ReactiveElasticsearchClientTests {
|
||||
@Test // DATAES-488
|
||||
public void indexShouldErrorForExistingDocuments() {
|
||||
|
||||
String id = addSourceDocument().ofType(TYPE_I).to(INDEX_I);
|
||||
String id = addSourceDocument().to(INDEX_I);
|
||||
|
||||
IndexRequest request = indexRequest(DOC_SOURCE, INDEX_I, TYPE_I)//
|
||||
IndexRequest request = indexRequest()//
|
||||
.id(id);
|
||||
|
||||
client.index(request) //
|
||||
@@ -331,7 +331,7 @@ public class ReactiveElasticsearchClientTests {
|
||||
@Test // DATAES-488
|
||||
public void updateShouldUpdateExistingDocument() {
|
||||
|
||||
String id = addSourceDocument().ofType(TYPE_I).to(INDEX_I);
|
||||
String id = addSourceDocument().to(INDEX_I);
|
||||
|
||||
UpdateRequest request = new UpdateRequest(INDEX_I, id) //
|
||||
.doc(Collections.singletonMap("dutiful", "farseer"));
|
||||
@@ -362,7 +362,7 @@ public class ReactiveElasticsearchClientTests {
|
||||
@Test // DATAES-488
|
||||
public void deleteShouldRemoveExistingDocument() {
|
||||
|
||||
String id = addSourceDocument().ofType(TYPE_I).to(INDEX_I);
|
||||
String id = addSourceDocument().to(INDEX_I);
|
||||
|
||||
DeleteRequest request = new DeleteRequest(INDEX_I, id);
|
||||
|
||||
@@ -375,7 +375,7 @@ public class ReactiveElasticsearchClientTests {
|
||||
@Test // DATAES-488
|
||||
public void deleteShouldReturnNotFoundForNonExistingDocument() {
|
||||
|
||||
addSourceDocument().ofType(TYPE_I).to(INDEX_I);
|
||||
addSourceDocument().to(INDEX_I);
|
||||
|
||||
DeleteRequest request = new DeleteRequest(INDEX_I, "this-one-does-not-exist");
|
||||
|
||||
@@ -388,8 +388,8 @@ public class ReactiveElasticsearchClientTests {
|
||||
@Test // DATAES-488
|
||||
public void searchShouldFindExistingDocuments() {
|
||||
|
||||
addSourceDocument().ofType(TYPE_I).to(INDEX_I);
|
||||
addSourceDocument().ofType(TYPE_I).to(INDEX_I);
|
||||
addSourceDocument().to(INDEX_I);
|
||||
addSourceDocument().to(INDEX_I);
|
||||
|
||||
SearchRequest request = new SearchRequest(INDEX_I) //
|
||||
.source(new SearchSourceBuilder().query(QueryBuilders.matchAllQuery()));
|
||||
@@ -401,9 +401,9 @@ public class ReactiveElasticsearchClientTests {
|
||||
}
|
||||
|
||||
@Test // DATAES-488
|
||||
public void searchShouldCompleteIfNothingFound() throws IOException {
|
||||
public void searchShouldCompleteIfNothingFound() {
|
||||
|
||||
syncClient.indices().create(new CreateIndexRequest(INDEX_I), RequestOptions.DEFAULT);
|
||||
operations.indexOps(IndexCoordinates.of(INDEX_I)).create().block();
|
||||
|
||||
SearchRequest request = new SearchRequest(INDEX_I) //
|
||||
.source(new SearchSourceBuilder().query(QueryBuilders.matchAllQuery()));
|
||||
@@ -414,10 +414,9 @@ public class ReactiveElasticsearchClientTests {
|
||||
}
|
||||
|
||||
@Test // DATAES-488
|
||||
@ElasticsearchVersion(asOf = "6.5.0")
|
||||
public void deleteByShouldRemoveExistingDocument() {
|
||||
|
||||
String id = addSourceDocument().ofType(TYPE_I).to(INDEX_I);
|
||||
String id = addSourceDocument().to(INDEX_I);
|
||||
|
||||
DeleteByQueryRequest request = new DeleteByQueryRequest(INDEX_I) //
|
||||
.setQuery(QueryBuilders.boolQuery().must(QueryBuilders.termQuery("_id", id)));
|
||||
@@ -430,10 +429,9 @@ public class ReactiveElasticsearchClientTests {
|
||||
}
|
||||
|
||||
@Test // DATAES-488
|
||||
@ElasticsearchVersion(asOf = "6.5.0")
|
||||
public void deleteByEmitResultWhenNothingRemoved() {
|
||||
|
||||
addSourceDocument().ofType(TYPE_I).to(INDEX_I);
|
||||
addSourceDocument().to(INDEX_I);
|
||||
|
||||
DeleteByQueryRequest request = new DeleteByQueryRequest(INDEX_I) //
|
||||
.setQuery(QueryBuilders.boolQuery().must(QueryBuilders.termQuery("_id", "it-was-not-me")));
|
||||
@@ -448,7 +446,7 @@ public class ReactiveElasticsearchClientTests {
|
||||
@Test // DATAES-510
|
||||
public void scrollShouldReadWhileEndNotReached() {
|
||||
|
||||
IntStream.range(0, 100).forEach(it -> add(Collections.singletonMap(it + "-foo", "bar")).ofType(TYPE_I).to(INDEX_I));
|
||||
IntStream.range(0, 100).forEach(it -> add(Collections.singletonMap(it + "-foo", "bar")).to(INDEX_I));
|
||||
|
||||
SearchRequest request = new SearchRequest(INDEX_I) //
|
||||
.source(new SearchSourceBuilder().query(QueryBuilders.matchAllQuery()));
|
||||
@@ -464,7 +462,7 @@ public class ReactiveElasticsearchClientTests {
|
||||
@Test // DATAES-510
|
||||
public void scrollShouldReadWhileTakeNotReached() {
|
||||
|
||||
IntStream.range(0, 100).forEach(it -> add(Collections.singletonMap(it + "-foo", "bar")).ofType(TYPE_I).to(INDEX_I));
|
||||
IntStream.range(0, 100).forEach(it -> add(Collections.singletonMap(it + "-foo", "bar")).to(INDEX_I));
|
||||
|
||||
SearchRequest request = new SearchRequest(INDEX_I) //
|
||||
.source(new SearchSourceBuilder().query(QueryBuilders.matchAllQuery()));
|
||||
@@ -479,9 +477,9 @@ public class ReactiveElasticsearchClientTests {
|
||||
}
|
||||
|
||||
@Test // DATAES-569
|
||||
public void indexExistsShouldReturnTrueIfSo() throws IOException {
|
||||
public void indexExistsShouldReturnTrueIfSo() {
|
||||
|
||||
syncClient.indices().create(new CreateIndexRequest(INDEX_I), RequestOptions.DEFAULT);
|
||||
operations.indexOps(IndexCoordinates.of(INDEX_I)).create().block();
|
||||
|
||||
client.indices().existsIndex(request -> request.indices(INDEX_I)) //
|
||||
.as(StepVerifier::create) //
|
||||
@@ -490,9 +488,9 @@ public class ReactiveElasticsearchClientTests {
|
||||
}
|
||||
|
||||
@Test // DATAES-569
|
||||
public void indexExistsShouldReturnFalseIfNot() throws IOException {
|
||||
public void indexExistsShouldReturnFalseIfNot() {
|
||||
|
||||
syncClient.indices().create(new CreateIndexRequest(INDEX_I), RequestOptions.DEFAULT);
|
||||
operations.indexOps(IndexCoordinates.of(INDEX_I)).create().block();
|
||||
|
||||
client.indices().existsIndex(request -> request.indices(INDEX_II)) //
|
||||
.as(StepVerifier::create) //
|
||||
@@ -501,20 +499,23 @@ public class ReactiveElasticsearchClientTests {
|
||||
}
|
||||
|
||||
@Test // DATAES-569, DATAES-678
|
||||
public void createIndex() throws IOException {
|
||||
public void createIndex() {
|
||||
|
||||
client.indices().createIndex(request -> request.index(INDEX_I)) //
|
||||
.as(StepVerifier::create) //
|
||||
.expectNext(true) //
|
||||
.verifyComplete();
|
||||
|
||||
assertThat(syncClient.indices().exists(new GetIndexRequest(INDEX_I), RequestOptions.DEFAULT)).isTrue();
|
||||
operations.indexOps(IndexCoordinates.of(INDEX_I)).exists() //
|
||||
.as(StepVerifier::create) //
|
||||
.expectNext(true) //
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
@Test // DATAES-569
|
||||
public void createExistingIndexErrors() throws IOException {
|
||||
public void createExistingIndexErrors() {
|
||||
|
||||
syncClient.indices().create(new CreateIndexRequest(INDEX_I), RequestOptions.DEFAULT);
|
||||
operations.indexOps(IndexCoordinates.of(INDEX_I)).create().block();
|
||||
|
||||
client.indices().createIndex(request -> request.index(INDEX_I)) //
|
||||
.as(StepVerifier::create) //
|
||||
@@ -522,16 +523,20 @@ public class ReactiveElasticsearchClientTests {
|
||||
}
|
||||
|
||||
@Test // DATAES-569, DATAES-678
|
||||
public void deleteExistingIndex() throws IOException {
|
||||
public void deleteExistingIndex() {
|
||||
|
||||
syncClient.indices().create(new CreateIndexRequest(INDEX_I), RequestOptions.DEFAULT);
|
||||
operations.indexOps(IndexCoordinates.of(INDEX_I)).create().block();
|
||||
|
||||
client.indices().deleteIndex(request -> request.indices(INDEX_I)) //
|
||||
.as(StepVerifier::create) //
|
||||
.expectNext(true) //
|
||||
.verifyComplete();
|
||||
|
||||
assertThat(syncClient.indices().exists(new GetIndexRequest(INDEX_I), RequestOptions.DEFAULT)).isFalse();
|
||||
operations.indexOps(IndexCoordinates.of(INDEX_I)) //
|
||||
.exists() //
|
||||
.as(StepVerifier::create) //
|
||||
.expectNext(false) //
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
@Test // DATAES-569, DATAES-767
|
||||
@@ -543,9 +548,9 @@ public class ReactiveElasticsearchClientTests {
|
||||
}
|
||||
|
||||
@Test // DATAES-569
|
||||
public void openExistingIndex() throws IOException {
|
||||
public void openExistingIndex() {
|
||||
|
||||
syncClient.indices().create(new CreateIndexRequest(INDEX_I), RequestOptions.DEFAULT);
|
||||
operations.indexOps(IndexCoordinates.of(INDEX_I)).create().block();
|
||||
|
||||
client.indices().openIndex(request -> request.indices(INDEX_I)) //
|
||||
.as(StepVerifier::create) //
|
||||
@@ -561,9 +566,9 @@ public class ReactiveElasticsearchClientTests {
|
||||
}
|
||||
|
||||
@Test // DATAES-569
|
||||
public void closeExistingIndex() throws IOException {
|
||||
public void closeExistingIndex() {
|
||||
|
||||
syncClient.indices().create(new CreateIndexRequest(INDEX_I), RequestOptions.DEFAULT);
|
||||
operations.indexOps(IndexCoordinates.of(INDEX_I)).create().block();
|
||||
|
||||
client.indices().openIndex(request -> request.indices(INDEX_I)) //
|
||||
.as(StepVerifier::create) //
|
||||
@@ -579,9 +584,9 @@ public class ReactiveElasticsearchClientTests {
|
||||
}
|
||||
|
||||
@Test // DATAES-569
|
||||
public void refreshIndex() throws IOException {
|
||||
public void refreshIndex() {
|
||||
|
||||
syncClient.indices().create(new CreateIndexRequest(INDEX_I), RequestOptions.DEFAULT);
|
||||
operations.indexOps(IndexCoordinates.of(INDEX_I)).create().block();
|
||||
|
||||
client.indices().refreshIndex(request -> request.indices(INDEX_I)) //
|
||||
.as(StepVerifier::create) //
|
||||
@@ -597,14 +602,14 @@ public class ReactiveElasticsearchClientTests {
|
||||
}
|
||||
|
||||
@Test // DATAES-569
|
||||
public void updateMapping() throws IOException {
|
||||
public void updateMapping() {
|
||||
|
||||
syncClient.indices().create(new CreateIndexRequest(INDEX_I), RequestOptions.DEFAULT);
|
||||
operations.indexOps(IndexCoordinates.of(INDEX_I)).create().block();
|
||||
|
||||
Map<String, Object> jsonMap = Collections.singletonMap("properties",
|
||||
Collections.singletonMap("message", Collections.singletonMap("type", "text")));
|
||||
|
||||
client.indices().updateMapping(request -> request.indices(INDEX_I).type(TYPE_I).source(jsonMap)) //
|
||||
client.indices().updateMapping(request -> request.indices(INDEX_I).source(jsonMap)) //
|
||||
.as(StepVerifier::create) //
|
||||
.expectNext(true) //
|
||||
.verifyComplete();
|
||||
@@ -616,15 +621,15 @@ public class ReactiveElasticsearchClientTests {
|
||||
Map<String, Object> jsonMap = Collections.singletonMap("properties",
|
||||
Collections.singletonMap("message", Collections.singletonMap("type", "text")));
|
||||
|
||||
client.indices().updateMapping(request -> request.indices(INDEX_I).type(TYPE_I).source(jsonMap)) //
|
||||
client.indices().updateMapping(request -> request.indices(INDEX_I).source(jsonMap)) //
|
||||
.as(StepVerifier::create) //
|
||||
.verifyError(ElasticsearchStatusException.class);
|
||||
}
|
||||
|
||||
@Test // DATAES-569
|
||||
public void flushIndex() throws IOException {
|
||||
public void flushIndex() {
|
||||
|
||||
syncClient.indices().create(new CreateIndexRequest(INDEX_I), RequestOptions.DEFAULT);
|
||||
operations.indexOps(IndexCoordinates.of(INDEX_I)).create().block();
|
||||
|
||||
client.indices().flushIndex(request -> request.indices(INDEX_I)) //
|
||||
.as(StepVerifier::create) //
|
||||
@@ -641,8 +646,8 @@ public class ReactiveElasticsearchClientTests {
|
||||
|
||||
@Test // DATAES-684
|
||||
public void bulkShouldUpdateExistingDocument() {
|
||||
String idFirstDoc = addSourceDocument().ofType(TYPE_I).to(INDEX_I);
|
||||
String idSecondDoc = addSourceDocument().ofType(TYPE_I).to(INDEX_I);
|
||||
String idFirstDoc = addSourceDocument().to(INDEX_I);
|
||||
String idSecondDoc = addSourceDocument().to(INDEX_I);
|
||||
|
||||
UpdateRequest requestFirstDoc = new UpdateRequest(INDEX_I, idFirstDoc) //
|
||||
.doc(Collections.singletonMap("dutiful", "farseer"));
|
||||
@@ -666,13 +671,15 @@ public class ReactiveElasticsearchClientTests {
|
||||
}
|
||||
|
||||
@Test // DATAES-567
|
||||
public void aggregateReturnsAggregationResults() throws IOException {
|
||||
syncClient.indices().create(new CreateIndexRequest(INDEX_I), RequestOptions.DEFAULT);
|
||||
public void aggregateReturnsAggregationResults() {
|
||||
ReactiveIndexOperations indexOps = operations.indexOps(IndexCoordinates.of(INDEX_I));
|
||||
indexOps.create().block();
|
||||
|
||||
Map<String, Object> jsonMap = Collections.singletonMap("properties",
|
||||
Collections.singletonMap("firstname", Collections.singletonMap("type", "keyword")));
|
||||
syncClient.indices().putMapping(new PutMappingRequest(INDEX_I).source(jsonMap), RequestOptions.DEFAULT);
|
||||
indexOps.putMapping(Mono.just(Document.from(jsonMap))).block();
|
||||
|
||||
addSourceDocument().ofType(TYPE_I).to(INDEX_I);
|
||||
addSourceDocument().to(INDEX_I);
|
||||
|
||||
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder().query(QueryBuilders.matchAllQuery());
|
||||
searchSourceBuilder.aggregation(AggregationBuilders.terms("terms").field("firstname"));
|
||||
@@ -685,13 +692,14 @@ public class ReactiveElasticsearchClientTests {
|
||||
}
|
||||
|
||||
@Test // DATAES-866
|
||||
public void suggestReturnsSuggestionResults() throws IOException {
|
||||
syncClient.indices().create(new CreateIndexRequest(INDEX_I), RequestOptions.DEFAULT);
|
||||
public void suggestReturnsSuggestionResults() {
|
||||
ReactiveIndexOperations indexOps = operations.indexOps(IndexCoordinates.of(INDEX_I));
|
||||
indexOps.create().block();
|
||||
Map<String, Object> jsonMap = Collections.singletonMap("properties",
|
||||
Collections.singletonMap("firstname", Collections.singletonMap("type", "completion")));
|
||||
syncClient.indices().putMapping(new PutMappingRequest(INDEX_I).source(jsonMap), RequestOptions.DEFAULT);
|
||||
indexOps.putMapping(Mono.just(Document.from(jsonMap))).block();
|
||||
|
||||
addSourceDocument().ofType(TYPE_I).to(INDEX_I);
|
||||
addSourceDocument().to(INDEX_I);
|
||||
|
||||
SuggestBuilder suggestBuilder = new SuggestBuilder().addSuggestion("firstname",
|
||||
new CompletionSuggestionBuilder("firstname").prefix("ch"));
|
||||
@@ -708,55 +716,43 @@ public class ReactiveElasticsearchClientTests {
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
private AddToIndexOfType addSourceDocument() {
|
||||
private AddToIndex addSourceDocument() {
|
||||
return add(DOC_SOURCE);
|
||||
}
|
||||
|
||||
private AddToIndexOfType add(Map<String, ?> source) {
|
||||
private AddToIndex add(Map<String, ?> source) {
|
||||
return new AddDocument(source);
|
||||
}
|
||||
|
||||
private IndexRequest indexRequest(Map source, String index, String type) {
|
||||
private IndexRequest indexRequest() {
|
||||
|
||||
return new IndexRequest(index) //
|
||||
return new IndexRequest(ReactiveElasticsearchClientTests.INDEX_I) //
|
||||
.id(UUID.randomUUID().toString()) //
|
||||
.source(source) //
|
||||
.source(ReactiveElasticsearchClientTests.DOC_SOURCE) //
|
||||
.setRefreshPolicy(RefreshPolicy.IMMEDIATE) //
|
||||
.create(true);
|
||||
}
|
||||
|
||||
@SneakyThrows
|
||||
private String doIndex(Map<?, ?> source, String index, String type) {
|
||||
return syncClient.index(indexRequest(source, index, type), RequestOptions.DEFAULT).getId();
|
||||
}
|
||||
|
||||
interface AddToIndexOfType extends AddToIndex {
|
||||
AddToIndex ofType(String type);
|
||||
private String doIndex(Map<String, ?> source, String index) {
|
||||
return operations.save(source, IndexCoordinates.of(index)).block().get("id").toString();
|
||||
}
|
||||
|
||||
interface AddToIndex {
|
||||
String to(String index);
|
||||
}
|
||||
|
||||
class AddDocument implements AddToIndexOfType {
|
||||
class AddDocument implements AddToIndex {
|
||||
|
||||
Map<String, ?> source;
|
||||
@Nullable String type;
|
||||
|
||||
AddDocument(Map<String, ?> source) {
|
||||
this.source = source;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AddToIndex ofType(String type) {
|
||||
|
||||
this.type = type;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String to(String index) {
|
||||
return doIndex(new LinkedHashMap<>(source), index, type);
|
||||
return doIndex(new LinkedHashMap<>(source), index);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@ import lombok.NoArgsConstructor;
|
||||
import reactor.core.publisher.Mono;
|
||||
import reactor.test.StepVerifier;
|
||||
|
||||
import java.lang.Boolean;
|
||||
import java.lang.Long;
|
||||
import java.lang.Object;
|
||||
import java.net.ConnectException;
|
||||
@@ -49,6 +50,9 @@ import org.elasticsearch.search.sort.SortOrder;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.dao.DataAccessResourceFailureException;
|
||||
import org.springframework.dao.OptimisticLockingFailureException;
|
||||
import org.springframework.data.annotation.Id;
|
||||
@@ -56,7 +60,6 @@ import org.springframework.data.annotation.Version;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.elasticsearch.TestUtils;
|
||||
import org.springframework.data.elasticsearch.UncategorizedElasticsearchException;
|
||||
import org.springframework.data.elasticsearch.annotations.Document;
|
||||
import org.springframework.data.elasticsearch.annotations.Field;
|
||||
@@ -64,7 +67,7 @@ import org.springframework.data.elasticsearch.annotations.Score;
|
||||
import org.springframework.data.elasticsearch.client.reactive.ReactiveElasticsearchClient;
|
||||
import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates;
|
||||
import org.springframework.data.elasticsearch.core.query.*;
|
||||
import org.springframework.data.elasticsearch.junit.junit4.ElasticsearchVersion;
|
||||
import org.springframework.data.elasticsearch.junit.jupiter.ReactiveElasticsearchRestTemplateConfiguration;
|
||||
import org.springframework.data.elasticsearch.junit.jupiter.SpringIntegrationTest;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
@@ -83,25 +86,26 @@ import org.springframework.util.StringUtils;
|
||||
@SpringIntegrationTest
|
||||
public class ReactiveElasticsearchTemplateTests {
|
||||
|
||||
@Configuration
|
||||
@Import({ ReactiveElasticsearchRestTemplateConfiguration.class })
|
||||
static class Config {}
|
||||
|
||||
static final String DEFAULT_INDEX = "reactive-template-test-index";
|
||||
static final String ALTERNATE_INDEX = "reactive-template-tests-alternate-index";
|
||||
|
||||
private ElasticsearchRestTemplate restTemplate;
|
||||
private ReactiveElasticsearchTemplate template;
|
||||
private IndexOperations indexOperations;
|
||||
@Autowired private ReactiveElasticsearchTemplate template;
|
||||
private ReactiveIndexOperations indexOperations;
|
||||
|
||||
@BeforeEach
|
||||
public void setUp() {
|
||||
restTemplate = new ElasticsearchRestTemplate(TestUtils.restHighLevelClient());
|
||||
indexOperations = restTemplate.indexOps(SampleEntity.class);
|
||||
indexOperations = template.indexOps(SampleEntity.class);
|
||||
|
||||
deleteIndices();
|
||||
|
||||
indexOperations.create();
|
||||
indexOperations.putMapping(SampleEntity.class);
|
||||
indexOperations.refresh();
|
||||
|
||||
template = new ReactiveElasticsearchTemplate(TestUtils.reactiveClient(), restTemplate.getElasticsearchConverter());
|
||||
indexOperations.create() //
|
||||
.then(indexOperations.putMapping(SampleEntity.class)) //
|
||||
.then(indexOperations.refresh()) //
|
||||
.block(); //
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
@@ -110,9 +114,13 @@ public class ReactiveElasticsearchTemplateTests {
|
||||
}
|
||||
|
||||
private void deleteIndices() {
|
||||
TestUtils.deleteIndex(DEFAULT_INDEX, ALTERNATE_INDEX, "rx-template-test-index-this", "rx-template-test-index-that",
|
||||
"test-index-reactive-optimistic-entity-template",
|
||||
"test-index-reactive-optimistic-and-versioned-entity-template");
|
||||
template.indexOps(IndexCoordinates.of(DEFAULT_INDEX)).delete().block();
|
||||
template.indexOps(IndexCoordinates.of(ALTERNATE_INDEX)).delete().block();
|
||||
template.indexOps(IndexCoordinates.of("rx-template-test-index-this")).delete().block();
|
||||
template.indexOps(IndexCoordinates.of("rx-template-test-index-that")).delete().block();
|
||||
template.indexOps(IndexCoordinates.of("test-index-reactive-optimistic-entity-template")).delete().block();
|
||||
template.indexOps(IndexCoordinates.of("test-index-reactive-optimistic-and-versioned-entity-template")).delete()
|
||||
.block();
|
||||
}
|
||||
|
||||
@Test // DATAES-504
|
||||
@@ -147,10 +155,12 @@ public class ReactiveElasticsearchTemplateTests {
|
||||
|
||||
indexOperations.refresh();
|
||||
|
||||
SearchHits<SampleEntity> result = restTemplate.search(
|
||||
new CriteriaQuery(Criteria.where("message").is(sampleEntity.getMessage())), SampleEntity.class,
|
||||
IndexCoordinates.of(DEFAULT_INDEX));
|
||||
assertThat(result).hasSize(1);
|
||||
template
|
||||
.search(new CriteriaQuery(Criteria.where("message").is(sampleEntity.getMessage())), SampleEntity.class,
|
||||
IndexCoordinates.of(DEFAULT_INDEX)) //
|
||||
.as(StepVerifier::create) //
|
||||
.expectNextCount(1) //
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
@Test // DATAES-504
|
||||
@@ -159,17 +169,17 @@ public class ReactiveElasticsearchTemplateTests {
|
||||
SampleEntity sampleEntity = SampleEntity.builder().message("wohoo").build();
|
||||
|
||||
template.save(sampleEntity) //
|
||||
.as(StepVerifier::create) //
|
||||
.consumeNextWith(it -> {
|
||||
|
||||
assertThat(it.getId()).isNotNull();
|
||||
|
||||
indexOperations.refresh();
|
||||
assertThat(TestUtils.documentWithId(it.getId()).existsIn(DEFAULT_INDEX)).isTrue();
|
||||
}) //
|
||||
.map(SampleEntity::getId) //
|
||||
.flatMap(id -> indexOperations.refresh().thenReturn(id)) //
|
||||
.flatMap(id -> documentWithIdExistsInIndex(id, DEFAULT_INDEX)).as(StepVerifier::create) //
|
||||
.expectNext(true) //
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
private Mono<Boolean> documentWithIdExistsInIndex(String id, String index) {
|
||||
return template.exists(id, IndexCoordinates.of(index));
|
||||
}
|
||||
|
||||
@Test // DATAES-504
|
||||
public void insertWithExplicitIndexNameShouldOverwriteMetadata() {
|
||||
|
||||
@@ -181,11 +191,11 @@ public class ReactiveElasticsearchTemplateTests {
|
||||
.expectNextCount(1)//
|
||||
.verifyComplete();
|
||||
|
||||
restTemplate.refresh(IndexCoordinates.of(DEFAULT_INDEX));
|
||||
restTemplate.refresh(alternateIndex);
|
||||
template.indexOps(IndexCoordinates.of(DEFAULT_INDEX)).refresh().block();
|
||||
template.indexOps(alternateIndex).refresh().block();
|
||||
|
||||
assertThat(TestUtils.documentWithId(sampleEntity.getId()).existsIn(DEFAULT_INDEX)).isFalse();
|
||||
assertThat(TestUtils.documentWithId(sampleEntity.getId()).existsIn(ALTERNATE_INDEX)).isTrue();
|
||||
assertThat(documentWithIdExistsInIndex(sampleEntity.getId(), DEFAULT_INDEX).block()).isFalse();
|
||||
assertThat(documentWithIdExistsInIndex(sampleEntity.getId(), ALTERNATE_INDEX).block()).isTrue();
|
||||
}
|
||||
|
||||
@Test // DATAES-504
|
||||
@@ -266,16 +276,14 @@ public class ReactiveElasticsearchTemplateTests {
|
||||
|
||||
SampleEntity sampleEntity = randomEntity("some message");
|
||||
|
||||
IndexQuery indexQuery = getIndexQuery(sampleEntity);
|
||||
|
||||
IndexCoordinates defaultIndex = IndexCoordinates.of(DEFAULT_INDEX);
|
||||
IndexCoordinates alternateIndex = IndexCoordinates.of(ALTERNATE_INDEX);
|
||||
|
||||
restTemplate.index(indexQuery, alternateIndex);
|
||||
indexOperations.refresh();
|
||||
|
||||
restTemplate.indexOps(defaultIndex).refresh();
|
||||
restTemplate.indexOps(alternateIndex).refresh();
|
||||
template.save(sampleEntity, alternateIndex) //
|
||||
.then(indexOperations.refresh()) //
|
||||
.then(template.indexOps(defaultIndex).refresh()) //
|
||||
.then(template.indexOps(alternateIndex).refresh()) //
|
||||
.block();
|
||||
|
||||
template.get(sampleEntity.getId(), SampleEntity.class, defaultIndex) //
|
||||
.as(StepVerifier::create) //
|
||||
@@ -612,7 +620,6 @@ public class ReactiveElasticsearchTemplateTests {
|
||||
}
|
||||
|
||||
@Test // DATAES-519
|
||||
@ElasticsearchVersion(asOf = "6.5.0")
|
||||
public void deleteByQueryShouldReturnZeroWhenIndexDoesNotExist() {
|
||||
|
||||
CriteriaQuery query = new CriteriaQuery(new Criteria("message").contains("test"));
|
||||
@@ -624,7 +631,6 @@ public class ReactiveElasticsearchTemplateTests {
|
||||
}
|
||||
|
||||
@Test // DATAES-547
|
||||
@ElasticsearchVersion(asOf = "6.5.0")
|
||||
public void shouldDeleteAcrossIndex() {
|
||||
|
||||
String indexPrefix = "rx-template-test-index";
|
||||
@@ -637,8 +643,7 @@ public class ReactiveElasticsearchTemplateTests {
|
||||
.as(StepVerifier::create)//
|
||||
.verifyComplete();
|
||||
|
||||
restTemplate.refresh(thisIndex);
|
||||
restTemplate.refresh(thatIndex);
|
||||
template.indexOps(thisIndex).refresh().then(template.indexOps(thatIndex).refresh()).block();
|
||||
|
||||
NativeSearchQuery searchQuery = new NativeSearchQueryBuilder() //
|
||||
.withQuery(termQuery("message", "test")) //
|
||||
@@ -649,11 +654,10 @@ public class ReactiveElasticsearchTemplateTests {
|
||||
.expectNext(2L) //
|
||||
.verifyComplete();
|
||||
|
||||
TestUtils.deleteIndex(thisIndex.getIndexName(), thatIndex.getIndexName());
|
||||
template.indexOps(thisIndex).delete().then(template.indexOps(thatIndex).delete()).block();
|
||||
}
|
||||
|
||||
@Test // DATAES-547
|
||||
@ElasticsearchVersion(asOf = "6.5.0")
|
||||
public void shouldDeleteAcrossIndexWhenNoMatchingDataPresent() {
|
||||
|
||||
String indexPrefix = "rx-template-test-index";
|
||||
@@ -666,8 +670,7 @@ public class ReactiveElasticsearchTemplateTests {
|
||||
.as(StepVerifier::create)//
|
||||
.verifyComplete();
|
||||
|
||||
restTemplate.refresh(thisIndex);
|
||||
restTemplate.refresh(thatIndex);
|
||||
template.indexOps(thisIndex).refresh().then(template.indexOps(thatIndex).refresh()).block();
|
||||
|
||||
NativeSearchQuery searchQuery = new NativeSearchQueryBuilder() //
|
||||
.withQuery(termQuery("message", "negative")) //
|
||||
@@ -678,11 +681,10 @@ public class ReactiveElasticsearchTemplateTests {
|
||||
.expectNext(0L) //
|
||||
.verifyComplete();
|
||||
|
||||
TestUtils.deleteIndex(thisIndex.getIndexName(), thatIndex.getIndexName());
|
||||
template.indexOps(thisIndex).delete().then(template.indexOps(thatIndex).delete()).block();
|
||||
}
|
||||
|
||||
@Test // DATAES-504
|
||||
@ElasticsearchVersion(asOf = "6.5.0")
|
||||
public void deleteByQueryShouldReturnNumberOfDeletedDocuments() {
|
||||
|
||||
index(randomEntity("test message"), randomEntity("test test"), randomEntity("some message"));
|
||||
@@ -696,7 +698,6 @@ public class ReactiveElasticsearchTemplateTests {
|
||||
}
|
||||
|
||||
@Test // DATAES-504
|
||||
@ElasticsearchVersion(asOf = "6.5.0")
|
||||
public void deleteByQueryShouldReturnZeroIfNothingDeleted() {
|
||||
|
||||
index(randomEntity("test message"));
|
||||
@@ -896,7 +897,8 @@ public class ReactiveElasticsearchTemplateTests {
|
||||
OptimisticEntity original = new OptimisticEntity();
|
||||
original.setMessage("It's fine");
|
||||
OptimisticEntity saved = template.save(original).block();
|
||||
restTemplate.refresh(OptimisticEntity.class);
|
||||
|
||||
template.indexOps(OptimisticEntity.class).refresh().block();
|
||||
|
||||
template
|
||||
.search(searchQueryForOne(saved.getId()), OptimisticEntity.class,
|
||||
@@ -1050,12 +1052,10 @@ public class ReactiveElasticsearchTemplateTests {
|
||||
IndexCoordinates indexCoordinates = IndexCoordinates.of(DEFAULT_INDEX);
|
||||
|
||||
if (entities.length == 1) {
|
||||
restTemplate.index(getIndexQuery(entities[0]), indexCoordinates);
|
||||
template.save(entities[0], indexCoordinates).then(indexOperations.refresh()).block();
|
||||
} else {
|
||||
restTemplate.bulkIndex(getIndexQueries(entities), indexCoordinates);
|
||||
template.saveAll(Mono.just(Arrays.asList(entities)), indexCoordinates).then(indexOperations.refresh()).block();
|
||||
}
|
||||
|
||||
indexOperations.refresh();
|
||||
}
|
||||
|
||||
@Data
|
||||
|
||||
@@ -1,45 +0,0 @@
|
||||
/*
|
||||
* Copyright 2018-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.data.elasticsearch.junit.junit4;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* @author Christoph Strobl
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.METHOD)
|
||||
@Documented
|
||||
public @interface ElasticsearchVersion {
|
||||
|
||||
/**
|
||||
* Inclusive lower bound of Elasticsearch server range.
|
||||
*
|
||||
* @return {@code 0.0.0} by default.
|
||||
*/
|
||||
String asOf() default "0.0.0";
|
||||
|
||||
/**
|
||||
* Exclusive upper bound of Elasticsearch server range.
|
||||
*
|
||||
* @return {@code 9999.9999.9999} by default.
|
||||
*/
|
||||
String until() default "9999.9999.9999";
|
||||
}
|
||||
@@ -1,132 +0,0 @@
|
||||
/*
|
||||
* Copyright 2018-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.data.elasticsearch.junit.junit4;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import org.junit.AssumptionViolatedException;
|
||||
import org.junit.rules.TestRule;
|
||||
import org.junit.runner.Description;
|
||||
import org.junit.runners.model.Statement;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.data.elasticsearch.TestUtils;
|
||||
import org.springframework.data.util.Version;
|
||||
|
||||
/**
|
||||
* @author Christoph Strobl
|
||||
*/
|
||||
public class ElasticsearchVersionRule implements TestRule {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(ElasticsearchVersionRule.class);
|
||||
|
||||
private static final Version ANY = new Version(9999, 9999, 9999);
|
||||
private static final Version DEFAULT_HIGH = ANY;
|
||||
private static final Version DEFAULT_LOW = new Version(0, 0, 0);
|
||||
|
||||
private final static AtomicReference<Version> currentVersion = new AtomicReference<>(null);
|
||||
private final Version minVersion;
|
||||
private final Version maxVersion;
|
||||
|
||||
public ElasticsearchVersionRule(Version min, Version max) {
|
||||
|
||||
this.minVersion = min;
|
||||
this.maxVersion = max;
|
||||
}
|
||||
|
||||
public static ElasticsearchVersionRule any() {
|
||||
return new ElasticsearchVersionRule(ANY, ANY);
|
||||
}
|
||||
|
||||
public static ElasticsearchVersionRule atLeast(Version minVersion) {
|
||||
return new ElasticsearchVersionRule(minVersion, DEFAULT_HIGH);
|
||||
}
|
||||
|
||||
public static ElasticsearchVersionRule atMost(Version maxVersion) {
|
||||
return new ElasticsearchVersionRule(DEFAULT_LOW, maxVersion);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Statement apply(Statement base, Description description) {
|
||||
|
||||
return new Statement() {
|
||||
|
||||
@Override
|
||||
public void evaluate() throws Throwable {
|
||||
|
||||
if (!getCurrentVersion().equals(ANY)) {
|
||||
|
||||
Version minVersion = ElasticsearchVersionRule.this.minVersion.equals(ANY) ? DEFAULT_LOW
|
||||
: ElasticsearchVersionRule.this.minVersion;
|
||||
Version maxVersion = ElasticsearchVersionRule.this.maxVersion.equals(ANY) ? DEFAULT_HIGH
|
||||
: ElasticsearchVersionRule.this.maxVersion;
|
||||
|
||||
if (description.getAnnotation(ElasticsearchVersion.class) != null) {
|
||||
ElasticsearchVersion version = description.getAnnotation(ElasticsearchVersion.class);
|
||||
if (version != null) {
|
||||
|
||||
Version expectedMinVersion = Version.parse(version.asOf());
|
||||
if (!expectedMinVersion.equals(ANY) && !expectedMinVersion.equals(DEFAULT_LOW)) {
|
||||
minVersion = expectedMinVersion;
|
||||
}
|
||||
|
||||
Version expectedMaxVersion = Version.parse(version.until());
|
||||
if (!expectedMaxVersion.equals(ANY) && !expectedMaxVersion.equals(DEFAULT_HIGH)) {
|
||||
maxVersion = expectedMaxVersion;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
validateVersion(minVersion, maxVersion);
|
||||
}
|
||||
|
||||
base.evaluate();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private void validateVersion(Version min, Version max) {
|
||||
|
||||
if (getCurrentVersion().isLessThan(min) || getCurrentVersion().isGreaterThanOrEqualTo(max)) {
|
||||
|
||||
throw new AssumptionViolatedException(String
|
||||
.format("Expected Elasticsearch server to be in range (%s, %s] but found %s", min, max, currentVersion));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private Version getCurrentVersion() {
|
||||
|
||||
if (currentVersion.get() == null) {
|
||||
|
||||
Version current = fetchCurrentVersion();
|
||||
if (currentVersion.compareAndSet(null, current)) {
|
||||
logger.info("Running Elasticsearch " + current);
|
||||
}
|
||||
}
|
||||
|
||||
return currentVersion.get();
|
||||
}
|
||||
|
||||
private Version fetchCurrentVersion() {
|
||||
return TestUtils.serverVersion();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getCurrentVersion().toString();
|
||||
}
|
||||
}
|
||||
@@ -1,54 +0,0 @@
|
||||
/*
|
||||
* Copyright 2019-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.data.elasticsearch.junit.junit4;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.elasticsearch.client.Client;
|
||||
import org.elasticsearch.node.Node;
|
||||
import org.junit.rules.ExternalResource;
|
||||
import org.springframework.data.elasticsearch.Utils;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* JUnit4 Rule that sets up and tears down a local Elasticsearch node.
|
||||
*
|
||||
* @author Peter-Josef Meisch
|
||||
*/
|
||||
public class TestNodeResource extends ExternalResource {
|
||||
|
||||
private Node node;
|
||||
|
||||
@Override
|
||||
protected void before() throws Throwable {
|
||||
node = Utils.getNode();
|
||||
node.start();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void after() {
|
||||
if (node != null) {
|
||||
try {
|
||||
node.close();
|
||||
} catch (IOException ignored) {}
|
||||
}
|
||||
}
|
||||
|
||||
public Client client() {
|
||||
Assert.notNull(node, "node is not initialized");
|
||||
return node.client();
|
||||
}
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
/**
|
||||
* interfaces, annotations and classes related to JUnit 4 test handling.
|
||||
*/
|
||||
@org.springframework.lang.NonNullApi
|
||||
package org.springframework.data.elasticsearch.junit.junit4;
|
||||
@@ -15,42 +15,44 @@
|
||||
*/
|
||||
package org.springframework.data.elasticsearch.junit.jupiter;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
|
||||
import org.elasticsearch.node.Node;
|
||||
import org.elasticsearch.node.NodeValidationException;
|
||||
import org.junit.jupiter.api.extension.ExtensionContext;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.data.elasticsearch.Utils;
|
||||
import org.springframework.data.elasticsearch.support.VersionInfo;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.testcontainers.elasticsearch.ElasticsearchContainer;
|
||||
|
||||
/**
|
||||
* This class manages the connection to an Elasticsearch Cluster, starting a local one if necessary. The information
|
||||
* about the ClusterConnection is stored both as a variable in the instance for direct access from JUnit 5 and in a
|
||||
* static ThreadLocal<ClusterConnectionInfo> accessible with the {@link ClusterConnection#clusterConnectionInfo()}
|
||||
* method to be integrated in the Spring setup
|
||||
* This class manages the connection to an Elasticsearch Cluster, starting a containerized one if necessary. The
|
||||
* information about the ClusterConnection is stored both as a variable in the instance for direct access from JUnit 5
|
||||
* and in a static ThreadLocal<ClusterConnectionInfo> accessible with the
|
||||
* {@link ClusterConnection#clusterConnectionInfo()} method to be integrated in the Spring setup
|
||||
*
|
||||
* @author Peter-Josef Meisch
|
||||
*/
|
||||
class ClusterConnection implements ExtensionContext.Store.CloseableResource {
|
||||
public class ClusterConnection implements ExtensionContext.Store.CloseableResource {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(ClusterConnection.class);
|
||||
|
||||
private static final int ELASTICSEARCH_DEFAULT_PORT = 9200;
|
||||
private static final int ELASTICSEARCH_DEFAULT_TRANSPORT_PORT = 9300;
|
||||
private static final String ELASTICSEARCH_DEFAULT_IMAGE = "docker.elastic.co/elasticsearch/elasticsearch";
|
||||
|
||||
private static final ThreadLocal<ClusterConnectionInfo> clusterConnectionInfoThreadLocal = new ThreadLocal<>();
|
||||
|
||||
private Node node;
|
||||
private final ClusterConnectionInfo clusterConnectionInfo;
|
||||
@Nullable private final ClusterConnectionInfo clusterConnectionInfo;
|
||||
|
||||
/**
|
||||
* creates the ClusterConnection, starting a local node if necessary.
|
||||
* creates the ClusterConnection, starting a container if necessary.
|
||||
*
|
||||
* @param clusterUrl if null or empty a local cluster is tarted
|
||||
*/
|
||||
public ClusterConnection(@Nullable String clusterUrl) {
|
||||
clusterConnectionInfo = StringUtils.isEmpty(clusterUrl) ? startLocalNode() : parseUrl(clusterUrl);
|
||||
clusterConnectionInfo = StringUtils.isEmpty(clusterUrl) ? startElasticsearchContainer() : parseUrl(clusterUrl);
|
||||
|
||||
if (clusterConnectionInfo != null) {
|
||||
LOGGER.debug(clusterConnectionInfo.toString());
|
||||
@@ -68,6 +70,7 @@ class ClusterConnection implements ExtensionContext.Store.CloseableResource {
|
||||
return clusterConnectionInfoThreadLocal.get();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public ClusterConnectionInfo getClusterConnectionInfo() {
|
||||
return clusterConnectionInfo;
|
||||
}
|
||||
@@ -94,18 +97,27 @@ class ClusterConnection implements ExtensionContext.Store.CloseableResource {
|
||||
|
||||
}
|
||||
|
||||
private @Nullable ClusterConnectionInfo startLocalNode() {
|
||||
LOGGER.debug("starting local node");
|
||||
@Nullable
|
||||
private ClusterConnectionInfo startElasticsearchContainer() {
|
||||
|
||||
LOGGER.debug("Starting Elasticsearch Container");
|
||||
|
||||
try {
|
||||
node = Utils.getNode();
|
||||
node.start();
|
||||
String elasticsearchVersion = VersionInfo.versionProperties()
|
||||
.getProperty(VersionInfo.VERSION_ELASTICSEARCH_CLIENT);
|
||||
|
||||
String dockerImageName = ELASTICSEARCH_DEFAULT_IMAGE + ':' + elasticsearchVersion;
|
||||
LOGGER.debug("Docker image: {}", dockerImageName);
|
||||
ElasticsearchContainer elasticsearchContainer = new ElasticsearchContainer(dockerImageName);
|
||||
elasticsearchContainer.start();
|
||||
return ClusterConnectionInfo.builder() //
|
||||
.withHostAndPort("localhost", 9200) //
|
||||
.withClient(node.client()) //
|
||||
.withHostAndPort(elasticsearchContainer.getHost(),
|
||||
elasticsearchContainer.getMappedPort(ELASTICSEARCH_DEFAULT_PORT)) //
|
||||
.withTransportPort(elasticsearchContainer.getMappedPort(ELASTICSEARCH_DEFAULT_TRANSPORT_PORT)) //
|
||||
.withElasticsearchContainer(elasticsearchContainer) //
|
||||
.build();
|
||||
} catch (NodeValidationException e) {
|
||||
LOGGER.error("could not start local node", e);
|
||||
} catch (Exception e) {
|
||||
LOGGER.error("Could not start Elasticsearch container", e);
|
||||
}
|
||||
|
||||
return null;
|
||||
@@ -114,12 +126,11 @@ class ClusterConnection implements ExtensionContext.Store.CloseableResource {
|
||||
@Override
|
||||
public void close() {
|
||||
|
||||
if (node != null) {
|
||||
LOGGER.debug("closing node");
|
||||
try {
|
||||
node.close();
|
||||
} catch (IOException ignored) {}
|
||||
if (clusterConnectionInfo != null && clusterConnectionInfo.getElasticsearchContainer() != null) {
|
||||
LOGGER.debug("Stopping container");
|
||||
clusterConnectionInfo.getElasticsearchContainer().stop();
|
||||
}
|
||||
|
||||
LOGGER.debug("closed");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,16 +15,15 @@
|
||||
*/
|
||||
package org.springframework.data.elasticsearch.junit.jupiter;
|
||||
|
||||
import org.elasticsearch.client.Client;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.testcontainers.elasticsearch.ElasticsearchContainer;
|
||||
|
||||
/**
|
||||
* The information about the ClusterConnection. the {@link #client} field is only set if a local node is started,
|
||||
* otherwise it is null. <br/>
|
||||
* The information about the ClusterConnection.<br/>
|
||||
* The {@link #host}, {@link #httpPort} and {@link #useSsl} values specify the values needed to connect to the cluster
|
||||
* with a rest client for both a local started cluster and for one defined by the cluster URL when creating the
|
||||
* {@link ClusterConnection}. <br/>
|
||||
* {@link ClusterConnection}.<br/>
|
||||
* The object must be created by using a {@link ClusterConnectionInfo.Builder}.
|
||||
*
|
||||
* @author Peter-Josef Meisch
|
||||
@@ -33,23 +32,32 @@ public final class ClusterConnectionInfo {
|
||||
private final boolean useSsl;
|
||||
private final String host;
|
||||
private final int httpPort;
|
||||
private final Client client;
|
||||
private final int transportPort;
|
||||
private final String clusterName;
|
||||
@Nullable private final ElasticsearchContainer elasticsearchContainer;
|
||||
|
||||
public static Builder builder() {
|
||||
return new Builder();
|
||||
}
|
||||
|
||||
private ClusterConnectionInfo(String host, int httpPort, boolean useSsl, Client client) {
|
||||
private ClusterConnectionInfo(String host, int httpPort, boolean useSsl, int transportPort,
|
||||
@Nullable ElasticsearchContainer elasticsearchContainer) {
|
||||
this.host = host;
|
||||
this.httpPort = httpPort;
|
||||
this.useSsl = useSsl;
|
||||
this.client = client;
|
||||
this.transportPort = transportPort;
|
||||
this.elasticsearchContainer = elasticsearchContainer;
|
||||
this.clusterName = "docker-cluster";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ClusterConnectionInfo{" + "useSsl=" + useSsl + ", host='" + host + '\'' + ", httpPort=" + httpPort
|
||||
+ ", client=" + client + '}';
|
||||
return "ClusterConnectionInfo{" + //
|
||||
"useSsl=" + useSsl + //
|
||||
", host='" + host + '\'' + //
|
||||
", httpPort=" + httpPort + //
|
||||
", transportPort=" + transportPort + //
|
||||
'}'; //
|
||||
}
|
||||
|
||||
public String getHost() {
|
||||
@@ -60,20 +68,29 @@ public final class ClusterConnectionInfo {
|
||||
return httpPort;
|
||||
}
|
||||
|
||||
public int getTransportPort() {
|
||||
return transportPort;
|
||||
}
|
||||
|
||||
public String getClusterName() {
|
||||
return clusterName;
|
||||
}
|
||||
|
||||
public boolean isUseSsl() {
|
||||
return useSsl;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Client getClient() {
|
||||
return client;
|
||||
public ElasticsearchContainer getElasticsearchContainer() {
|
||||
return elasticsearchContainer;
|
||||
}
|
||||
|
||||
public static class Builder {
|
||||
boolean useSsl = false;
|
||||
private String host;
|
||||
private int httpPort;
|
||||
private Client client = null;
|
||||
private int transportPort;
|
||||
@Nullable private ElasticsearchContainer elasticsearchContainer;
|
||||
|
||||
public Builder withHostAndPort(String host, int httpPort) {
|
||||
Assert.hasLength(host, "host must not be empty");
|
||||
@@ -87,13 +104,18 @@ public final class ClusterConnectionInfo {
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder withClient(Client client) {
|
||||
this.client = client;
|
||||
public Builder withTransportPort(int transportPort) {
|
||||
this.transportPort = transportPort;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder withElasticsearchContainer(ElasticsearchContainer elasticsearchContainer) {
|
||||
this.elasticsearchContainer = elasticsearchContainer;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ClusterConnectionInfo build() {
|
||||
return new ClusterConnectionInfo(host, httpPort, useSsl, client);
|
||||
return new ClusterConnectionInfo(host, httpPort, useSsl, transportPort, elasticsearchContainer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,7 +15,14 @@
|
||||
*/
|
||||
package org.springframework.data.elasticsearch.junit.jupiter;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.net.UnknownHostException;
|
||||
|
||||
import org.elasticsearch.client.Client;
|
||||
import org.elasticsearch.client.transport.TransportClient;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.transport.TransportAddress;
|
||||
import org.elasticsearch.transport.client.PreBuiltTransportClient;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.elasticsearch.config.ElasticsearchConfigurationSupport;
|
||||
@@ -32,8 +39,14 @@ import org.springframework.data.elasticsearch.core.convert.ElasticsearchConverte
|
||||
public class ElasticsearchTemplateConfiguration extends ElasticsearchConfigurationSupport {
|
||||
|
||||
@Bean
|
||||
public Client elasticsearchClient(ClusterConnectionInfo clusterConnectionInfo) {
|
||||
return clusterConnectionInfo.getClient();
|
||||
public Client elasticsearchClient(ClusterConnectionInfo clusterConnectionInfo) throws UnknownHostException {
|
||||
|
||||
Settings settings = Settings.builder().put("cluster.name", clusterConnectionInfo.getClusterName()).build();
|
||||
TransportClient client = new PreBuiltTransportClient(settings);
|
||||
client.addTransportAddress(new TransportAddress(InetAddress.getByName(clusterConnectionInfo.getHost()),
|
||||
clusterConnectionInfo.getTransportPort()));
|
||||
|
||||
return client;
|
||||
}
|
||||
|
||||
@Bean(name = { "elasticsearchOperations", "elasticsearchTemplate" })
|
||||
|
||||
@@ -35,12 +35,14 @@ import org.junit.jupiter.api.AfterAll;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.elasticsearch.annotations.Document;
|
||||
import org.springframework.data.elasticsearch.annotations.Field;
|
||||
import org.springframework.data.elasticsearch.annotations.FieldType;
|
||||
import org.springframework.data.elasticsearch.annotations.InnerField;
|
||||
import org.springframework.data.elasticsearch.annotations.MultiField;
|
||||
import org.springframework.data.elasticsearch.junit.jupiter.SpringDataElasticsearchExtension;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
@@ -49,6 +51,7 @@ import org.springframework.lang.Nullable;
|
||||
* @author Christoph Strobl
|
||||
* @author Peter-Josef Meisch
|
||||
*/
|
||||
@ExtendWith(SpringDataElasticsearchExtension.class)
|
||||
public class CdiRepositoryTests {
|
||||
|
||||
@Nullable private static CdiTestContainer cdiContainer;
|
||||
|
||||
@@ -19,33 +19,31 @@ import javax.annotation.PreDestroy;
|
||||
import javax.enterprise.context.ApplicationScoped;
|
||||
import javax.enterprise.inject.Produces;
|
||||
|
||||
import org.elasticsearch.client.Client;
|
||||
import org.elasticsearch.node.NodeValidationException;
|
||||
import org.springframework.data.elasticsearch.Utils;
|
||||
import org.elasticsearch.client.RestHighLevelClient;
|
||||
import org.springframework.data.elasticsearch.client.ClientConfiguration;
|
||||
import org.springframework.data.elasticsearch.client.RestClients;
|
||||
import org.springframework.data.elasticsearch.core.ElasticsearchOperations;
|
||||
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
|
||||
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
|
||||
import org.springframework.data.elasticsearch.junit.jupiter.ClusterConnection;
|
||||
import org.springframework.data.elasticsearch.junit.jupiter.ClusterConnectionInfo;
|
||||
|
||||
/**
|
||||
* @author Mohsin Husen
|
||||
* @author Peter-Josef Meisch
|
||||
*/
|
||||
@ApplicationScoped
|
||||
class ElasticsearchTemplateProducer {
|
||||
class ElasticsearchOperationsProducer {
|
||||
|
||||
@Produces
|
||||
public Client createNodeClient() throws NodeValidationException {
|
||||
return Utils.getNodeClient();
|
||||
}
|
||||
|
||||
@Produces
|
||||
public ElasticsearchOperations createElasticsearchTemplate(Client client) {
|
||||
return new ElasticsearchTemplate(client);
|
||||
public ElasticsearchOperations createElasticsearchTemplate(RestHighLevelClient restHighLevelClient) {
|
||||
return new ElasticsearchRestTemplate(restHighLevelClient);
|
||||
}
|
||||
|
||||
@Produces
|
||||
@OtherQualifier
|
||||
@PersonDB
|
||||
public ElasticsearchOperations createQualifiedElasticsearchTemplate(Client client) {
|
||||
return new ElasticsearchTemplate(client);
|
||||
public ElasticsearchOperations createQualifiedElasticsearchTemplate(RestHighLevelClient restHighLevelClient) {
|
||||
return new ElasticsearchRestTemplate(restHighLevelClient);
|
||||
}
|
||||
|
||||
@PreDestroy
|
||||
@@ -53,4 +51,15 @@ class ElasticsearchTemplateProducer {
|
||||
// remove everything to avoid conflicts with other tests in case server not shut down properly
|
||||
}
|
||||
|
||||
@Produces
|
||||
public RestHighLevelClient elasticsearchClient() {
|
||||
// we rely on the tests being run with the SpringDataElasticsearchExtension class that sets up a containerized ES.
|
||||
ClusterConnectionInfo connectionInfo = ClusterConnection.clusterConnectionInfo();
|
||||
|
||||
ClientConfiguration clientConfiguration = ClientConfiguration.builder() //
|
||||
.connectedTo(connectionInfo.getHost() + ':' + connectionInfo.getHttpPort()) //
|
||||
.build();
|
||||
|
||||
return RestClients.create(clientConfiguration).rest();
|
||||
}
|
||||
}
|
||||
@@ -26,13 +26,12 @@ import org.assertj.core.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.elasticsearch.TestUtils;
|
||||
import org.springframework.data.elasticsearch.annotations.Document;
|
||||
import org.springframework.data.elasticsearch.annotations.Field;
|
||||
import org.springframework.data.elasticsearch.core.ReactiveElasticsearchTemplate;
|
||||
import org.springframework.data.elasticsearch.junit.jupiter.ReactiveElasticsearchRestTemplateConfiguration;
|
||||
import org.springframework.data.elasticsearch.junit.jupiter.SpringIntegrationTest;
|
||||
import org.springframework.data.elasticsearch.repository.ReactiveElasticsearchRepository;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
@@ -46,14 +45,9 @@ import org.springframework.test.context.ContextConfiguration;
|
||||
public class ReactiveElasticsearchRepositoriesRegistrarTests {
|
||||
|
||||
@Configuration
|
||||
@Import({ ReactiveElasticsearchRestTemplateConfiguration.class })
|
||||
@EnableReactiveElasticsearchRepositories(considerNestedRepositories = true)
|
||||
static class Config {
|
||||
|
||||
@Bean
|
||||
public ReactiveElasticsearchTemplate reactiveElasticsearchTemplate() {
|
||||
return new ReactiveElasticsearchTemplate(TestUtils.reactiveClient());
|
||||
}
|
||||
}
|
||||
static class Config {}
|
||||
|
||||
@Autowired ReactiveSampleEntityRepository repository;
|
||||
@Autowired ApplicationContext context;
|
||||
@@ -72,8 +66,7 @@ public class ReactiveElasticsearchRepositoriesRegistrarTests {
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Builder
|
||||
@Document(indexName = "test-index-sample-reactive-repositories-registrar",
|
||||
replicas = 0, refreshInterval = "-1")
|
||||
@Document(indexName = "test-index-sample-reactive-repositories-registrar", replicas = 0, refreshInterval = "-1")
|
||||
static class SampleEntity {
|
||||
|
||||
@Id private String id;
|
||||
|
||||
@@ -27,23 +27,13 @@ import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
import reactor.test.StepVerifier;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.Boolean;
|
||||
import java.lang.Long;
|
||||
import java.lang.Object;
|
||||
import java.util.Arrays;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
import org.elasticsearch.ElasticsearchStatusException;
|
||||
import org.elasticsearch.action.bulk.BulkRequest;
|
||||
import org.elasticsearch.action.index.IndexRequest;
|
||||
import org.elasticsearch.action.support.WriteRequest.RefreshPolicy;
|
||||
import org.elasticsearch.client.RequestOptions;
|
||||
import org.elasticsearch.client.RestHighLevelClient;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
@@ -57,22 +47,19 @@ import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.domain.Sort.Order;
|
||||
import org.springframework.data.elasticsearch.TestUtils;
|
||||
import org.springframework.data.elasticsearch.annotations.Document;
|
||||
import org.springframework.data.elasticsearch.annotations.Field;
|
||||
import org.springframework.data.elasticsearch.annotations.Highlight;
|
||||
import org.springframework.data.elasticsearch.annotations.HighlightField;
|
||||
import org.springframework.data.elasticsearch.annotations.Query;
|
||||
import org.springframework.data.elasticsearch.annotations.Score;
|
||||
import org.springframework.data.elasticsearch.client.reactive.ReactiveElasticsearchClient;
|
||||
import org.springframework.data.elasticsearch.config.AbstractReactiveElasticsearchConfiguration;
|
||||
import org.springframework.data.elasticsearch.core.ReactiveElasticsearchOperations;
|
||||
import org.springframework.data.elasticsearch.core.SearchHit;
|
||||
import org.springframework.data.elasticsearch.junit.jupiter.ElasticsearchRestTemplateConfiguration;
|
||||
import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates;
|
||||
import org.springframework.data.elasticsearch.junit.jupiter.ReactiveElasticsearchRestTemplateConfiguration;
|
||||
import org.springframework.data.elasticsearch.junit.jupiter.SpringIntegrationTest;
|
||||
import org.springframework.data.elasticsearch.repository.config.EnableReactiveElasticsearchRepositories;
|
||||
import org.springframework.data.repository.reactive.ReactiveCrudRepository;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* @author Christoph Strobl
|
||||
@@ -83,38 +70,37 @@ import org.springframework.util.StringUtils;
|
||||
public class SimpleReactiveElasticsearchRepositoryTests {
|
||||
|
||||
@Configuration
|
||||
@Import({ ElasticsearchRestTemplateConfiguration.class })
|
||||
@Import({ ReactiveElasticsearchRestTemplateConfiguration.class })
|
||||
@EnableReactiveElasticsearchRepositories(considerNestedRepositories = true)
|
||||
static class Config extends AbstractReactiveElasticsearchConfiguration {
|
||||
|
||||
@Override
|
||||
public ReactiveElasticsearchClient reactiveElasticsearchClient() {
|
||||
return TestUtils.reactiveClient();
|
||||
}
|
||||
}
|
||||
static class Config {}
|
||||
|
||||
static final String INDEX = "test-index-sample-simple-reactive";
|
||||
static final String TYPE = "test-type";
|
||||
|
||||
@Autowired ReactiveSampleEntityRepository repository;
|
||||
@Autowired ReactiveElasticsearchOperations operations;
|
||||
@SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection") @Autowired ReactiveSampleEntityRepository repository;
|
||||
|
||||
@BeforeEach
|
||||
public void setUp() {
|
||||
TestUtils.deleteIndex(INDEX);
|
||||
operations.indexOps(IndexCoordinates.of(INDEX)).delete().block();
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
void after() {
|
||||
TestUtils.deleteIndex(INDEX);
|
||||
operations.indexOps(IndexCoordinates.of(INDEX)).delete().block();
|
||||
}
|
||||
|
||||
@Test // DATAES-519
|
||||
public void saveShouldSaveSingleEntity() {
|
||||
|
||||
repository.save(SampleEntity.builder().build()) //
|
||||
.map(SampleEntity::getId) //
|
||||
.flatMap(this::documentWithIdExistsInIndex) //
|
||||
.as(StepVerifier::create) //
|
||||
.consumeNextWith(it -> assertThat(TestUtils.documentWithId(it.getId()).existsIn(INDEX)).isTrue()) //
|
||||
.verifyComplete();
|
||||
.expectNext(true).verifyComplete();
|
||||
}
|
||||
|
||||
private Mono<Boolean> documentWithIdExistsInIndex(String id) {
|
||||
return operations.exists(id, IndexCoordinates.of(INDEX));
|
||||
}
|
||||
|
||||
@Test // DATAES-519
|
||||
@@ -123,10 +109,12 @@ public class SimpleReactiveElasticsearchRepositoryTests {
|
||||
repository
|
||||
.saveAll(Arrays.asList(SampleEntity.builder().build(), SampleEntity.builder().build(),
|
||||
SampleEntity.builder().build())) //
|
||||
.map(SampleEntity::getId) //
|
||||
.flatMap(this::documentWithIdExistsInIndex) //
|
||||
.as(StepVerifier::create) //
|
||||
.consumeNextWith(it -> assertThat(TestUtils.documentWithId(it.getId()).existsIn(INDEX)).isTrue()) //
|
||||
.consumeNextWith(it -> assertThat(TestUtils.documentWithId(it.getId()).existsIn(INDEX)).isTrue()) //
|
||||
.consumeNextWith(it -> assertThat(TestUtils.documentWithId(it.getId()).existsIn(INDEX)).isTrue()) //
|
||||
.expectNext(true) //
|
||||
.expectNext(true) //
|
||||
.expectNext(true) //
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
@@ -138,11 +126,12 @@ public class SimpleReactiveElasticsearchRepositoryTests {
|
||||
}
|
||||
|
||||
@Test // DATAES-519
|
||||
public void findShouldRetrieveSingleEntityById() throws IOException {
|
||||
public void findShouldRetrieveSingleEntityById() {
|
||||
|
||||
bulkIndex(SampleEntity.builder().id("id-one").build(), //
|
||||
SampleEntity.builder().id("id-two").build(), //
|
||||
SampleEntity.builder().id("id-three").build());
|
||||
SampleEntity.builder().id("id-three").build()) //
|
||||
.block();
|
||||
|
||||
repository.findById("id-two").as(StepVerifier::create)//
|
||||
.consumeNextWith(it -> assertThat(it.getId()).isEqualTo("id-two")) //
|
||||
@@ -150,23 +139,25 @@ public class SimpleReactiveElasticsearchRepositoryTests {
|
||||
}
|
||||
|
||||
@Test // DATAES-519
|
||||
public void findByIdShouldCompleteIfNothingFound() throws IOException {
|
||||
public void findByIdShouldCompleteIfNothingFound() {
|
||||
|
||||
bulkIndex(SampleEntity.builder().id("id-one").build(), //
|
||||
SampleEntity.builder().id("id-two").build(), //
|
||||
SampleEntity.builder().id("id-three").build());
|
||||
SampleEntity.builder().id("id-three").build()) //
|
||||
.block();
|
||||
|
||||
repository.findById("does-not-exist").as(StepVerifier::create) //
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
@Test // DATAES-720
|
||||
public void findAllShouldReturnAllElements() throws IOException {
|
||||
public void findAllShouldReturnAllElements() {
|
||||
// make sure to be above the default page size of the Query interface
|
||||
int count = DEFAULT_PAGE_SIZE * 2;
|
||||
bulkIndex(IntStream.range(1, count + 1) //
|
||||
.mapToObj(it -> SampleEntity.builder().id(String.valueOf(it)).build()) //
|
||||
.toArray(SampleEntity[]::new));
|
||||
.toArray(SampleEntity[]::new)) //
|
||||
.block();
|
||||
|
||||
repository.findAll() //
|
||||
.as(StepVerifier::create) //
|
||||
@@ -180,11 +171,12 @@ public class SimpleReactiveElasticsearchRepositoryTests {
|
||||
}
|
||||
|
||||
@Test // DATAES-519
|
||||
public void findAllByIdShouldRetrieveMatchingDocuments() throws IOException {
|
||||
public void findAllByIdShouldRetrieveMatchingDocuments() {
|
||||
|
||||
bulkIndex(SampleEntity.builder().id("id-one").build(), //
|
||||
SampleEntity.builder().id("id-two").build(), //
|
||||
SampleEntity.builder().id("id-three").build());
|
||||
SampleEntity.builder().id("id-three").build()) //
|
||||
.block();
|
||||
|
||||
repository.findAllById(Arrays.asList("id-one", "id-two")) //
|
||||
.as(StepVerifier::create)//
|
||||
@@ -194,11 +186,12 @@ public class SimpleReactiveElasticsearchRepositoryTests {
|
||||
}
|
||||
|
||||
@Test // DATAES-519
|
||||
public void findAllByIdShouldCompleteWhenNothingFound() throws IOException {
|
||||
public void findAllByIdShouldCompleteWhenNothingFound() {
|
||||
|
||||
bulkIndex(SampleEntity.builder().id("id-one").build(), //
|
||||
SampleEntity.builder().id("id-two").build(), //
|
||||
SampleEntity.builder().id("id-three").build());
|
||||
SampleEntity.builder().id("id-three").build()) //
|
||||
.block();
|
||||
|
||||
repository.findAllById(Arrays.asList("can't", "touch", "this")) //
|
||||
.as(StepVerifier::create)//
|
||||
@@ -206,11 +199,12 @@ public class SimpleReactiveElasticsearchRepositoryTests {
|
||||
}
|
||||
|
||||
@Test // DATAES-717
|
||||
void shouldReturnFluxOfSearchHit() throws IOException {
|
||||
void shouldReturnFluxOfSearchHit() {
|
||||
|
||||
bulkIndex(SampleEntity.builder().id("id-one").message("message").build(), //
|
||||
SampleEntity.builder().id("id-two").message("message").build(), //
|
||||
SampleEntity.builder().id("id-three").message("message").build());
|
||||
SampleEntity.builder().id("id-three").message("message").build()) //
|
||||
.block();
|
||||
|
||||
repository.queryAllByMessage("message") //
|
||||
.as(StepVerifier::create) //
|
||||
@@ -220,11 +214,12 @@ public class SimpleReactiveElasticsearchRepositoryTests {
|
||||
}
|
||||
|
||||
@Test // DATAES-717
|
||||
void shouldReturnFluxOfSearchHitForStringQuery() throws IOException {
|
||||
void shouldReturnFluxOfSearchHitForStringQuery() {
|
||||
|
||||
bulkIndex(SampleEntity.builder().id("id-one").message("message").build(), //
|
||||
SampleEntity.builder().id("id-two").message("message").build(), //
|
||||
SampleEntity.builder().id("id-three").message("message").build());
|
||||
SampleEntity.builder().id("id-three").message("message").build()) //
|
||||
.block();
|
||||
|
||||
repository.queryByMessageWithString("message") //
|
||||
.as(StepVerifier::create) //
|
||||
@@ -234,11 +229,12 @@ public class SimpleReactiveElasticsearchRepositoryTests {
|
||||
}
|
||||
|
||||
@Test // DATAES-372
|
||||
void shouldReturnHighlightsOnAnnotatedMethod() throws IOException {
|
||||
void shouldReturnHighlightsOnAnnotatedMethod() {
|
||||
|
||||
bulkIndex(SampleEntity.builder().id("id-one").message("message").build(), //
|
||||
SampleEntity.builder().id("id-two").message("message").build(), //
|
||||
SampleEntity.builder().id("id-three").message("message").build());
|
||||
SampleEntity.builder().id("id-three").message("message").build()) //
|
||||
.block();
|
||||
|
||||
repository.queryAllByMessage("message") //
|
||||
.as(StepVerifier::create) //
|
||||
@@ -251,11 +247,12 @@ public class SimpleReactiveElasticsearchRepositoryTests {
|
||||
}
|
||||
|
||||
@Test // DATAES-372
|
||||
void shouldReturnHighlightsOnAnnotatedStringQueryMethod() throws IOException {
|
||||
void shouldReturnHighlightsOnAnnotatedStringQueryMethod() {
|
||||
|
||||
bulkIndex(SampleEntity.builder().id("id-one").message("message").build(), //
|
||||
SampleEntity.builder().id("id-two").message("message").build(), //
|
||||
SampleEntity.builder().id("id-three").message("message").build());
|
||||
SampleEntity.builder().id("id-three").message("message").build()) //
|
||||
.block();
|
||||
|
||||
repository.queryByMessageWithString("message") //
|
||||
.as(StepVerifier::create) //
|
||||
@@ -275,20 +272,22 @@ public class SimpleReactiveElasticsearchRepositoryTests {
|
||||
}
|
||||
|
||||
@Test // DATAES-519
|
||||
public void countShouldCountDocuments() throws IOException {
|
||||
public void countShouldCountDocuments() {
|
||||
|
||||
bulkIndex(SampleEntity.builder().id("id-one").build(), //
|
||||
SampleEntity.builder().id("id-two").build());
|
||||
SampleEntity.builder().id("id-two").build()) //
|
||||
.block();
|
||||
|
||||
repository.count().as(StepVerifier::create).expectNext(2L).verifyComplete();
|
||||
}
|
||||
|
||||
@Test // DATAES-519
|
||||
public void existsByIdShouldReturnTrueIfExists() throws IOException {
|
||||
public void existsByIdShouldReturnTrueIfExists() {
|
||||
|
||||
bulkIndex(SampleEntity.builder().id("id-one").message("message").build(), //
|
||||
SampleEntity.builder().id("id-two").message("test message").build(), //
|
||||
SampleEntity.builder().id("id-three").message("test test").build());
|
||||
SampleEntity.builder().id("id-three").message("test test").build()) //
|
||||
.block();
|
||||
|
||||
repository.existsById("id-two") //
|
||||
.as(StepVerifier::create) //
|
||||
@@ -297,11 +296,12 @@ public class SimpleReactiveElasticsearchRepositoryTests {
|
||||
}
|
||||
|
||||
@Test // DATAES-519
|
||||
public void existsByIdShouldReturnFalseIfNotExists() throws IOException {
|
||||
public void existsByIdShouldReturnFalseIfNotExists() {
|
||||
|
||||
bulkIndex(SampleEntity.builder().id("id-one").message("message").build(), //
|
||||
SampleEntity.builder().id("id-two").message("test message").build(), //
|
||||
SampleEntity.builder().id("id-three").message("test test").build());
|
||||
SampleEntity.builder().id("id-three").message("test test").build()) //
|
||||
.block();
|
||||
|
||||
repository.existsById("wrecking ball") //
|
||||
.as(StepVerifier::create) //
|
||||
@@ -310,11 +310,12 @@ public class SimpleReactiveElasticsearchRepositoryTests {
|
||||
}
|
||||
|
||||
@Test // DATAES-519
|
||||
public void countShouldCountMatchingDocuments() throws IOException {
|
||||
public void countShouldCountMatchingDocuments() {
|
||||
|
||||
bulkIndex(SampleEntity.builder().id("id-one").message("message").build(), //
|
||||
SampleEntity.builder().id("id-two").message("test message").build(), //
|
||||
SampleEntity.builder().id("id-three").message("test test").build());
|
||||
SampleEntity.builder().id("id-three").message("test test").build()) //
|
||||
.block();
|
||||
|
||||
repository.countAllByMessage("test") //
|
||||
.as(StepVerifier::create) //
|
||||
@@ -323,11 +324,12 @@ public class SimpleReactiveElasticsearchRepositoryTests {
|
||||
}
|
||||
|
||||
@Test // DATAES-519
|
||||
public void existsShouldReturnTrueIfExists() throws IOException {
|
||||
public void existsShouldReturnTrueIfExists() {
|
||||
|
||||
bulkIndex(SampleEntity.builder().id("id-one").message("message").build(), //
|
||||
SampleEntity.builder().id("id-two").message("test message").build(), //
|
||||
SampleEntity.builder().id("id-three").message("test test").build());
|
||||
SampleEntity.builder().id("id-three").message("test test").build()) //
|
||||
.block();
|
||||
|
||||
repository.existsAllByMessage("message") //
|
||||
.as(StepVerifier::create) //
|
||||
@@ -336,11 +338,12 @@ public class SimpleReactiveElasticsearchRepositoryTests {
|
||||
}
|
||||
|
||||
@Test // DATAES-519
|
||||
public void existsShouldReturnFalseIfNotExists() throws IOException {
|
||||
public void existsShouldReturnFalseIfNotExists() {
|
||||
|
||||
bulkIndex(SampleEntity.builder().id("id-one").message("message").build(), //
|
||||
SampleEntity.builder().id("id-two").message("test message").build(), //
|
||||
SampleEntity.builder().id("id-three").message("test test").build());
|
||||
SampleEntity.builder().id("id-three").message("test test").build()) //
|
||||
.block();
|
||||
|
||||
repository.existsAllByMessage("these days") //
|
||||
.as(StepVerifier::create) //
|
||||
@@ -349,10 +352,11 @@ public class SimpleReactiveElasticsearchRepositoryTests {
|
||||
}
|
||||
|
||||
@Test // DATAES-519
|
||||
public void deleteByIdShouldCompleteIfNothingDeleted() throws IOException {
|
||||
public void deleteByIdShouldCompleteIfNothingDeleted() {
|
||||
|
||||
bulkIndex(SampleEntity.builder().id("id-one").build(), //
|
||||
SampleEntity.builder().id("id-two").build());
|
||||
SampleEntity.builder().id("id-two").build()) //
|
||||
.block();
|
||||
|
||||
repository.deleteById("does-not-exist").as(StepVerifier::create).verifyComplete();
|
||||
}
|
||||
@@ -365,61 +369,69 @@ public class SimpleReactiveElasticsearchRepositoryTests {
|
||||
}
|
||||
|
||||
@Test // DATAES-519
|
||||
public void deleteByIdShouldDeleteEntry() throws IOException {
|
||||
public void deleteByIdShouldDeleteEntry() {
|
||||
|
||||
SampleEntity toBeDeleted = SampleEntity.builder().id("id-two").build();
|
||||
bulkIndex(SampleEntity.builder().id("id-one").build(), toBeDeleted);
|
||||
bulkIndex(SampleEntity.builder().id("id-one").build(), toBeDeleted) //
|
||||
.block();
|
||||
|
||||
repository.deleteById(toBeDeleted.getId()).as(StepVerifier::create).verifyComplete();
|
||||
|
||||
assertThat(TestUtils.documentWithId(toBeDeleted.getId()).ofType(TYPE).existsIn(INDEX)).isFalse();
|
||||
assertThat(documentWithIdExistsInIndex(toBeDeleted.getId()).block()).isFalse();
|
||||
}
|
||||
|
||||
@Test // DATAES-519
|
||||
public void deleteShouldDeleteEntry() throws IOException {
|
||||
public void deleteShouldDeleteEntry() {
|
||||
|
||||
SampleEntity toBeDeleted = SampleEntity.builder().id("id-two").build();
|
||||
bulkIndex(SampleEntity.builder().id("id-one").build(), toBeDeleted);
|
||||
bulkIndex(SampleEntity.builder().id("id-one").build(), toBeDeleted) //
|
||||
.block();
|
||||
|
||||
repository.delete(toBeDeleted).as(StepVerifier::create).verifyComplete();
|
||||
|
||||
assertThat(TestUtils.documentWithId(toBeDeleted.getId()).ofType(TYPE).existsIn(INDEX)).isFalse();
|
||||
assertThat(documentWithIdExistsInIndex(toBeDeleted.getId()).block()).isFalse();
|
||||
}
|
||||
|
||||
@Test // DATAES-519
|
||||
public void deleteAllShouldDeleteGivenEntries() throws IOException {
|
||||
public void deleteAllShouldDeleteGivenEntries() {
|
||||
|
||||
SampleEntity toBeDeleted = SampleEntity.builder().id("id-one").build();
|
||||
SampleEntity hangInThere = SampleEntity.builder().id("id-two").build();
|
||||
SampleEntity toBeDeleted2 = SampleEntity.builder().id("id-three").build();
|
||||
|
||||
bulkIndex(toBeDeleted, hangInThere, toBeDeleted2);
|
||||
bulkIndex(toBeDeleted, hangInThere, toBeDeleted2) //
|
||||
.block();
|
||||
|
||||
repository.deleteAll(Arrays.asList(toBeDeleted, toBeDeleted2)).as(StepVerifier::create).verifyComplete();
|
||||
|
||||
assertThat(TestUtils.documentWithId(toBeDeleted.getId()).ofType(TYPE).existsIn(INDEX)).isFalse();
|
||||
assertThat(TestUtils.documentWithId(toBeDeleted2.getId()).ofType(TYPE).existsIn(INDEX)).isFalse();
|
||||
assertThat(TestUtils.documentWithId(hangInThere.getId()).ofType(TYPE).existsIn(INDEX)).isTrue();
|
||||
assertThat(documentWithIdExistsInIndex(toBeDeleted.getId()).block()).isFalse();
|
||||
assertThat(documentWithIdExistsInIndex(toBeDeleted2.getId()).block()).isFalse();
|
||||
assertThat(documentWithIdExistsInIndex(hangInThere.getId()).block()).isTrue();
|
||||
}
|
||||
|
||||
@Test // DATAES-519
|
||||
public void deleteAllShouldDeleteAllEntries() throws IOException {
|
||||
public void deleteAllShouldDeleteAllEntries() {
|
||||
|
||||
bulkIndex(SampleEntity.builder().id("id-one").build(), //
|
||||
SampleEntity.builder().id("id-two").build(), //
|
||||
SampleEntity.builder().id("id-three").build());
|
||||
SampleEntity.builder().id("id-three").build()) //
|
||||
.block();
|
||||
|
||||
repository.deleteAll().as(StepVerifier::create).verifyComplete();
|
||||
|
||||
assertThat(TestUtils.isEmptyIndex(INDEX)).isTrue();
|
||||
repository.count() //
|
||||
.as(StepVerifier::create) //
|
||||
.expectNext(0L) //
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
@Test // DATAES-519
|
||||
public void derivedFinderMethodShouldBeExecutedCorrectly() throws IOException {
|
||||
public void derivedFinderMethodShouldBeExecutedCorrectly() {
|
||||
|
||||
bulkIndex(SampleEntity.builder().id("id-one").message("message").build(), //
|
||||
SampleEntity.builder().id("id-two").message("test message").build(), //
|
||||
SampleEntity.builder().id("id-three").message("test test").build());
|
||||
SampleEntity.builder().id("id-three").message("test test").build()) //
|
||||
.block();
|
||||
|
||||
repository.findAllByMessageLike("test") //
|
||||
.as(StepVerifier::create) //
|
||||
@@ -428,11 +440,12 @@ public class SimpleReactiveElasticsearchRepositoryTests {
|
||||
}
|
||||
|
||||
@Test // DATAES-519
|
||||
public void derivedFinderMethodShouldBeExecutedCorrectlyWhenGivenPublisher() throws IOException {
|
||||
public void derivedFinderMethodShouldBeExecutedCorrectlyWhenGivenPublisher() {
|
||||
|
||||
bulkIndex(SampleEntity.builder().id("id-one").message("message").build(), //
|
||||
SampleEntity.builder().id("id-two").message("test message").build(), //
|
||||
SampleEntity.builder().id("id-three").message("test test").build());
|
||||
SampleEntity.builder().id("id-three").message("test test").build()) //
|
||||
.block();
|
||||
|
||||
repository.findAllByMessage(Mono.just("test")) //
|
||||
.as(StepVerifier::create) //
|
||||
@@ -441,11 +454,12 @@ public class SimpleReactiveElasticsearchRepositoryTests {
|
||||
}
|
||||
|
||||
@Test // DATAES-519
|
||||
public void derivedFinderWithDerivedSortMethodShouldBeExecutedCorrectly() throws IOException {
|
||||
public void derivedFinderWithDerivedSortMethodShouldBeExecutedCorrectly() {
|
||||
|
||||
bulkIndex(SampleEntity.builder().id("id-one").message("test").rate(3).build(), //
|
||||
SampleEntity.builder().id("id-two").message("test test").rate(1).build(), //
|
||||
SampleEntity.builder().id("id-three").message("test test").rate(2).build());
|
||||
SampleEntity.builder().id("id-three").message("test test").rate(2).build()) //
|
||||
.block();
|
||||
|
||||
repository.findAllByMessageLikeOrderByRate("test") //
|
||||
.as(StepVerifier::create) //
|
||||
@@ -456,11 +470,12 @@ public class SimpleReactiveElasticsearchRepositoryTests {
|
||||
}
|
||||
|
||||
@Test // DATAES-519
|
||||
public void derivedFinderMethodWithSortParameterShouldBeExecutedCorrectly() throws IOException {
|
||||
public void derivedFinderMethodWithSortParameterShouldBeExecutedCorrectly() {
|
||||
|
||||
bulkIndex(SampleEntity.builder().id("id-one").message("test").rate(3).build(), //
|
||||
SampleEntity.builder().id("id-two").message("test test").rate(1).build(), //
|
||||
SampleEntity.builder().id("id-three").message("test test").rate(2).build());
|
||||
SampleEntity.builder().id("id-three").message("test test").rate(2).build()) //
|
||||
.block();
|
||||
|
||||
repository.findAllByMessage("test", Sort.by(Order.asc("rate"))) //
|
||||
.as(StepVerifier::create) //
|
||||
@@ -471,11 +486,12 @@ public class SimpleReactiveElasticsearchRepositoryTests {
|
||||
}
|
||||
|
||||
@Test // DATAES-519
|
||||
public void derivedFinderMethodWithPageableParameterShouldBeExecutedCorrectly() throws IOException {
|
||||
public void derivedFinderMethodWithPageableParameterShouldBeExecutedCorrectly() {
|
||||
|
||||
bulkIndex(SampleEntity.builder().id("id-one").message("test").rate(3).build(), //
|
||||
SampleEntity.builder().id("id-two").message("test test").rate(1).build(), //
|
||||
SampleEntity.builder().id("id-three").message("test test").rate(2).build());
|
||||
SampleEntity.builder().id("id-three").message("test test").rate(2).build()) //
|
||||
.block();
|
||||
|
||||
repository.findAllByMessage("test", PageRequest.of(0, 2, Sort.by(Order.asc("rate")))) //
|
||||
.as(StepVerifier::create) //
|
||||
@@ -485,11 +501,12 @@ public class SimpleReactiveElasticsearchRepositoryTests {
|
||||
}
|
||||
|
||||
@Test // DATAES-519
|
||||
public void derivedFinderMethodReturningMonoShouldBeExecutedCorrectly() throws IOException {
|
||||
public void derivedFinderMethodReturningMonoShouldBeExecutedCorrectly() {
|
||||
|
||||
bulkIndex(SampleEntity.builder().id("id-one").message("message").build(), //
|
||||
SampleEntity.builder().id("id-two").message("test message").build(), //
|
||||
SampleEntity.builder().id("id-three").message("test test").build());
|
||||
SampleEntity.builder().id("id-three").message("test test").build()) //
|
||||
.block();
|
||||
|
||||
repository.findFirstByMessageLike("test") //
|
||||
.as(StepVerifier::create) //
|
||||
@@ -498,11 +515,12 @@ public class SimpleReactiveElasticsearchRepositoryTests {
|
||||
}
|
||||
|
||||
@Test // DATAES-519
|
||||
public void annotatedFinderMethodShouldBeExecutedCorrectly() throws IOException {
|
||||
public void annotatedFinderMethodShouldBeExecutedCorrectly() {
|
||||
|
||||
bulkIndex(SampleEntity.builder().id("id-one").message("message").build(), //
|
||||
SampleEntity.builder().id("id-two").message("test message").build(), //
|
||||
SampleEntity.builder().id("id-three").message("test test").build());
|
||||
SampleEntity.builder().id("id-three").message("test test").build()) //
|
||||
.block();
|
||||
|
||||
repository.findAllViaAnnotatedQueryByMessageLike("test") //
|
||||
.as(StepVerifier::create) //
|
||||
@@ -511,60 +529,25 @@ public class SimpleReactiveElasticsearchRepositoryTests {
|
||||
}
|
||||
|
||||
@Test // DATAES-519
|
||||
public void derivedDeleteMethodShouldBeExecutedCorrectly() throws IOException {
|
||||
public void derivedDeleteMethodShouldBeExecutedCorrectly() {
|
||||
|
||||
bulkIndex(SampleEntity.builder().id("id-one").message("message").build(), //
|
||||
SampleEntity.builder().id("id-two").message("test message").build(), //
|
||||
SampleEntity.builder().id("id-three").message("test test").build());
|
||||
SampleEntity.builder().id("id-three").message("test test").build()) //
|
||||
.block();
|
||||
|
||||
repository.deleteAllByMessage("message") //
|
||||
.as(StepVerifier::create) //
|
||||
.expectNext(2L) //
|
||||
.verifyComplete();
|
||||
|
||||
assertThat(TestUtils.documentWithId("id-one").ofType(TYPE).existsIn(INDEX)).isFalse();
|
||||
assertThat(TestUtils.documentWithId("id-two").ofType(TYPE).existsIn(INDEX)).isFalse();
|
||||
assertThat(TestUtils.documentWithId("id-three").ofType(TYPE).existsIn(INDEX)).isTrue();
|
||||
assertThat(documentWithIdExistsInIndex("id-one").block()).isFalse();
|
||||
assertThat(documentWithIdExistsInIndex("id-two").block()).isFalse();
|
||||
assertThat(documentWithIdExistsInIndex("id-three").block()).isTrue();
|
||||
}
|
||||
|
||||
private IndexRequest indexRequest(Map<String, ?> source, String index) {
|
||||
|
||||
return new IndexRequest(index) //
|
||||
.id(source.containsKey("id") ? source.get("id").toString() : UUID.randomUUID().toString()) //
|
||||
.source(source) //
|
||||
.create(true);
|
||||
}
|
||||
|
||||
private IndexRequest indexRequestFrom(SampleEntity entity) {
|
||||
|
||||
Map<String, Object> target = new LinkedHashMap<>();
|
||||
|
||||
if (StringUtils.hasText(entity.getId())) {
|
||||
target.put("id", entity.getId());
|
||||
}
|
||||
|
||||
if (StringUtils.hasText(entity.getType())) {
|
||||
target.put("type", entity.getType());
|
||||
}
|
||||
|
||||
if (StringUtils.hasText(entity.getMessage())) {
|
||||
target.put("message", entity.getMessage());
|
||||
}
|
||||
|
||||
target.put("rate", entity.getRate());
|
||||
target.put("available", entity.isAvailable());
|
||||
|
||||
return indexRequest(target, INDEX);
|
||||
}
|
||||
|
||||
void bulkIndex(SampleEntity... entities) throws IOException {
|
||||
|
||||
BulkRequest request = new BulkRequest();
|
||||
Arrays.stream(entities).forEach(it -> request.add(indexRequestFrom(it)));
|
||||
|
||||
try (RestHighLevelClient client = TestUtils.restHighLevelClient()) {
|
||||
client.bulk(request.setRefreshPolicy(RefreshPolicy.IMMEDIATE), RequestOptions.DEFAULT);
|
||||
}
|
||||
Mono<Void> bulkIndex(SampleEntity... entities) {
|
||||
return operations.saveAll(Arrays.asList(entities), IndexCoordinates.of(INDEX)).then();
|
||||
}
|
||||
|
||||
interface ReactiveSampleEntityRepository extends ReactiveCrudRepository<SampleEntity, String> {
|
||||
@@ -617,7 +600,6 @@ public class SimpleReactiveElasticsearchRepositoryTests {
|
||||
private int rate;
|
||||
private boolean available;
|
||||
@Version private Long version;
|
||||
@Score private float score;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user