Compare commits
13 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| afa611ce09 | |||
| dc9db5dcdc | |||
| 4ee592cd21 | |||
| cd7b6f8420 | |||
| 237c0ead2e | |||
| 6462305521 | |||
| 0a2038505f | |||
| 8276023132 | |||
| ae94120d91 | |||
| d2df9e7f4c | |||
| 73fc8f65ee | |||
| 4d2e4ac22c | |||
| 8d02946186 |
@@ -5,12 +5,12 @@
|
||||
|
||||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-elasticsearch</artifactId>
|
||||
<version>4.0.1.RELEASE</version>
|
||||
<version>4.0.2.RELEASE</version>
|
||||
|
||||
<parent>
|
||||
<groupId>org.springframework.data.build</groupId>
|
||||
<artifactId>spring-data-parent</artifactId>
|
||||
<version>2.3.1.RELEASE</version>
|
||||
<version>2.3.2.RELEASE</version>
|
||||
</parent>
|
||||
|
||||
<name>Spring Data Elasticsearch</name>
|
||||
@@ -21,7 +21,7 @@
|
||||
<commonslang>2.6</commonslang>
|
||||
<elasticsearch>7.6.2</elasticsearch>
|
||||
<log4j>2.9.1</log4j>
|
||||
<springdata.commons>2.3.1.RELEASE</springdata.commons>
|
||||
<springdata.commons>2.3.2.RELEASE</springdata.commons>
|
||||
<netty>4.1.39.Final</netty>
|
||||
<java-module-name>spring.data.elasticsearch</java-module-name>
|
||||
</properties>
|
||||
|
||||
@@ -20,5 +20,5 @@ package org.springframework.data.elasticsearch.annotations;
|
||||
* @since 4.0
|
||||
*/
|
||||
public enum TermVector {
|
||||
none, no, yes, with_positions, with_offsets, woth_positions_offsets, with_positions_payloads, with_positions_offets_payloads
|
||||
none, no, yes, with_positions, with_offsets, with_positions_offsets, with_positions_payloads, with_positions_offets_payloads
|
||||
}
|
||||
|
||||
+60
-31
@@ -804,53 +804,82 @@ public class DefaultReactiveElasticsearchClient implements ReactiveElasticsearch
|
||||
|
||||
private <T> Publisher<? extends T> handleServerError(Request request, ClientResponse response) {
|
||||
|
||||
RestStatus status = RestStatus.fromCode(response.statusCode().value());
|
||||
int statusCode = response.statusCode().value();
|
||||
RestStatus status = RestStatus.fromCode(statusCode);
|
||||
String mediaType = response.headers().contentType().map(MediaType::toString).orElse(XContentType.JSON.mediaType());
|
||||
|
||||
return Mono.error(new ElasticsearchStatusException(String.format("%s request to %s returned error code %s.",
|
||||
request.getMethod(), request.getEndpoint(), response.statusCode().value()), status));
|
||||
return response.body(BodyExtractors.toMono(byte[].class)) //
|
||||
.map(bytes -> new String(bytes, StandardCharsets.UTF_8)) //
|
||||
.flatMap(content -> contentOrError(content, mediaType, status))
|
||||
.flatMap(unused -> Mono
|
||||
.error(new ElasticsearchStatusException(String.format("%s request to %s returned error code %s.",
|
||||
request.getMethod(), request.getEndpoint(), statusCode), status)));
|
||||
}
|
||||
|
||||
private <T> Publisher<? extends T> handleClientError(String logId, Request request, ClientResponse response,
|
||||
Class<T> responseType) {
|
||||
|
||||
int statusCode = response.statusCode().value();
|
||||
RestStatus status = RestStatus.fromCode(statusCode);
|
||||
String mediaType = response.headers().contentType().map(MediaType::toString).orElse(XContentType.JSON.mediaType());
|
||||
|
||||
return response.body(BodyExtractors.toMono(byte[].class)) //
|
||||
.map(bytes -> new String(bytes, StandardCharsets.UTF_8)) //
|
||||
.flatMap(content -> {
|
||||
String mediaType = response.headers().contentType().map(MediaType::toString)
|
||||
.orElse(XContentType.JSON.mediaType());
|
||||
RestStatus status = RestStatus.fromCode(response.statusCode().value());
|
||||
try {
|
||||
ElasticsearchException exception = getElasticsearchException(response, content, mediaType);
|
||||
if (exception != null) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
buildExceptionMessages(sb, exception);
|
||||
return Mono.error(new ElasticsearchStatusException(sb.toString(), status, exception));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
return Mono.error(new ElasticsearchStatusException(content, status));
|
||||
}
|
||||
return Mono.just(content);
|
||||
}).doOnNext(it -> ClientLogger.logResponse(logId, response.statusCode(), it)) //
|
||||
.flatMap(content -> contentOrError(content, mediaType, status)) //
|
||||
.doOnNext(content -> ClientLogger.logResponse(logId, response.statusCode(), content)) //
|
||||
.flatMap(content -> doDecode(response, responseType, content));
|
||||
}
|
||||
|
||||
// region ElasticsearchException helper
|
||||
/**
|
||||
* checks if the given content body contains an {@link ElasticsearchException}, if yes it is returned in a Mono.error.
|
||||
* Otherwise the content is returned in the Mono
|
||||
*
|
||||
* @param content the content to analyze
|
||||
* @param mediaType the returned media type
|
||||
* @param status the response status
|
||||
* @return a Mono with the content or an Mono.error
|
||||
*/
|
||||
private static Mono<String> contentOrError(String content, String mediaType, RestStatus status) {
|
||||
|
||||
ElasticsearchException exception = getElasticsearchException(content, mediaType, status);
|
||||
|
||||
if (exception != null) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
buildExceptionMessages(sb, exception);
|
||||
return Mono.error(new ElasticsearchStatusException(sb.toString(), status, exception));
|
||||
}
|
||||
|
||||
return Mono.just(content);
|
||||
}
|
||||
|
||||
/**
|
||||
* tries to parse an {@link ElasticsearchException} from the given body content
|
||||
*
|
||||
* @param content the content to analyse
|
||||
* @param mediaType the type of the body content
|
||||
* @return an {@link ElasticsearchException} or {@literal null}.
|
||||
*/
|
||||
@Nullable
|
||||
private ElasticsearchException getElasticsearchException(ClientResponse response, String content, String mediaType)
|
||||
throws IOException {
|
||||
private static ElasticsearchException getElasticsearchException(String content, String mediaType, RestStatus status) {
|
||||
|
||||
XContentParser parser = createParser(mediaType, content);
|
||||
// we have a JSON object with an error and a status field
|
||||
XContentParser.Token token = parser.nextToken(); // Skip START_OBJECT
|
||||
try {
|
||||
XContentParser parser = createParser(mediaType, content);
|
||||
// we have a JSON object with an error and a status field
|
||||
XContentParser.Token token = parser.nextToken(); // Skip START_OBJECT
|
||||
|
||||
do {
|
||||
token = parser.nextToken();
|
||||
do {
|
||||
token = parser.nextToken();
|
||||
|
||||
if (parser.currentName().equals("error")) {
|
||||
return ElasticsearchException.failureFromXContent(parser);
|
||||
}
|
||||
} while (token == XContentParser.Token.FIELD_NAME);
|
||||
return null;
|
||||
if (parser.currentName().equals("error")) {
|
||||
return ElasticsearchException.failureFromXContent(parser);
|
||||
}
|
||||
} while (token == XContentParser.Token.FIELD_NAME);
|
||||
|
||||
return null;
|
||||
} catch (IOException e) {
|
||||
return new ElasticsearchStatusException(content, status);
|
||||
}
|
||||
}
|
||||
|
||||
private static void buildExceptionMessages(StringBuilder sb, Throwable t) {
|
||||
|
||||
@@ -38,8 +38,8 @@ public abstract class ResourceUtil {
|
||||
/**
|
||||
* Read a {@link ClassPathResource} into a {@link String}.
|
||||
*
|
||||
* @param url
|
||||
* @return
|
||||
* @param url url the file url
|
||||
* @return the contents of the file or null if it could not be read
|
||||
*/
|
||||
@Nullable
|
||||
public static String readFileFromClasspath(String url) {
|
||||
@@ -48,7 +48,7 @@ public abstract class ResourceUtil {
|
||||
try (InputStream is = classPathResource.getInputStream()) {
|
||||
return StreamUtils.copyToString(is, Charset.defaultCharset());
|
||||
} catch (Exception e) {
|
||||
LOGGER.debug(String.format("Failed to load file from url: %s: %s", url, e.getMessage()));
|
||||
LOGGER.warn(String.format("Failed to load file from url: %s: %s", url, e.getMessage()));
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
+3
-1
@@ -596,7 +596,9 @@ public class MappingElasticsearchConverter
|
||||
Map<Object, Object> target = new LinkedHashMap<>();
|
||||
Streamable<Entry<String, Object>> mapSource = Streamable.of(value.entrySet());
|
||||
|
||||
if (!typeHint.getActualType().getType().equals(Object.class)
|
||||
TypeInformation<?> actualType = typeHint.getActualType();
|
||||
|
||||
if (actualType != null && !actualType.getType().equals(Object.class)
|
||||
&& isSimpleType(typeHint.getMapValueType().getType())) {
|
||||
mapSource.forEach(it -> {
|
||||
|
||||
|
||||
@@ -1,6 +1,61 @@
|
||||
Spring Data Elasticsearch Changelog
|
||||
===================================
|
||||
|
||||
Changes in version 4.0.2.RELEASE (2020-07-22)
|
||||
---------------------------------------------
|
||||
* DATAES-883 - Fix log level on resource load error.
|
||||
* DATAES-878 - Wrong value for TermVector(woth_positions_offsets).
|
||||
* DATAES-865 - Fix MappingElasticsearchConverter writing an Object property containing a Map.
|
||||
* DATAES-863 - Improve server error response handling.
|
||||
* DATAES-862 - Release 4.0.2 (Neumann SR2).
|
||||
|
||||
|
||||
Changes in version 3.2.9.RELEASE (2020-07-22)
|
||||
---------------------------------------------
|
||||
* DATAES-861 - Release 3.2.9 (Moore SR9).
|
||||
|
||||
|
||||
Changes in version 3.1.19.RELEASE (2020-07-22)
|
||||
----------------------------------------------
|
||||
* DATAES-860 - Release 3.1.19 (Lovelace SR19).
|
||||
|
||||
|
||||
Changes in version 4.1.0-M1 (2020-06-25)
|
||||
----------------------------------------
|
||||
* DATAES-870 - Workaround for reactor-netty error.
|
||||
* DATAES-868 - Upgrade to Netty 4.1.50.Final.
|
||||
* DATAES-867 - Adopt to changes in Reactor Netty 1.0.
|
||||
* DATAES-866 - Implement suggest search in reactive client.
|
||||
* DATAES-865 - Fix MappingElasticsearchConverter writing an Object property containing a Map.
|
||||
* DATAES-863 - Improve server error response handling.
|
||||
* DATAES-859 - Don't use randomNumeric() in tests.
|
||||
* DATAES-858 - Use standard Spring code of conduct.
|
||||
* DATAES-857 - Registered simple types are not read from list.
|
||||
* DATAES-853 - Cleanup tests that do not delete test indices.
|
||||
* DATAES-852 - Upgrade to Elasticsearch 7.7.1.
|
||||
* DATAES-850 - Add warning and documentation for missing TemporalAccessor configuration.
|
||||
* DATAES-848 - Add the name of the index to SearchHit.
|
||||
* DATAES-847 - Add missing DateFormat values.
|
||||
* DATAES-845 - MappingElasticsearchConverter crashes when writing lists containing null values.
|
||||
* DATAES-844 - Improve TOC formatting for migration guides.
|
||||
* DATAES-841 - Remove deprecated type mappings code.
|
||||
* DATAES-840 - Consolidate index name SpEL resolution.
|
||||
* DATAES-839 - ReactiveElasticsearchTemplate should use RequestFactory.
|
||||
* DATAES-838 - Update to Elasticsearch 7.7.0.
|
||||
* DATAES-836 - Fix typo in Javadocs.
|
||||
* DATAES-835 - Fix code sample in documentation for scroll API.
|
||||
* DATAES-832 - findAllById repository method returns iterable with null elements for not found ids.
|
||||
* DATAES-831 - SearchOperations.searchForStream does not use requested maxResults.
|
||||
* DATAES-829 - Deprecate AbstractElasticsearchRepository and cleanup SimpleElasticsearchRepository.
|
||||
* DATAES-828 - Fields of type date need to have a format defined.
|
||||
* DATAES-827 - Repositories should not try to create an index when it already exists.
|
||||
* DATAES-826 - Add method to IndexOperations to write an index mapping from a entity class.
|
||||
* DATAES-825 - Update readme to use latest spring.io docs.
|
||||
* DATAES-824 - Release 4.1 M1 (2020.0.0).
|
||||
* DATAES-678 - Introduce ReactiveIndexOperations.
|
||||
* DATAES-263 - Inner Hits support.
|
||||
|
||||
|
||||
Changes in version 4.0.1.RELEASE (2020-06-10)
|
||||
---------------------------------------------
|
||||
* DATAES-857 - Registered simple types are not read from list.
|
||||
@@ -1171,5 +1226,9 @@ Release Notes - Spring Data Elasticsearch - Version 1.0 M1 (2014-02-07)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
Spring Data Elasticsearch 4.0.1
|
||||
Spring Data Elasticsearch 4.0.2 (Neumann SR2)
|
||||
Copyright (c) [2013-2019] Pivotal Software, Inc.
|
||||
|
||||
This product is licensed to you under the Apache License, Version 2.0 (the "License").
|
||||
@@ -16,3 +16,4 @@ conditions of the subcomponent's license, as noted in the LICENSE file.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
+30
@@ -789,6 +789,30 @@ public class MappingElasticsearchConverterUnitTests {
|
||||
assertThat(entity.locations).containsExactly(new GeoPoint(12.34, 23.45), new GeoPoint(34.56, 45.67));
|
||||
}
|
||||
|
||||
@Test // DATAES-865
|
||||
void shouldWriteEntityWithMapAsObject() throws JSONException {
|
||||
|
||||
Map<String, Object> map = new LinkedHashMap<>();
|
||||
map.put("foo", "bar");
|
||||
|
||||
EntityWithObject entity = new EntityWithObject();
|
||||
entity.setId("42");
|
||||
entity.setContent(map);
|
||||
|
||||
String expected = "{\n" + //
|
||||
" \"id\": \"42\",\n" + //
|
||||
" \"content\": {\n" + //
|
||||
" \"foo\": \"bar\"\n" + //
|
||||
" }\n" + //
|
||||
"}\n"; //
|
||||
|
||||
Document document = Document.create();
|
||||
|
||||
mappingElasticsearchConverter.write(entity, document);
|
||||
|
||||
assertEquals(expected, document.toJson(), false);
|
||||
}
|
||||
|
||||
private String pointTemplate(String name, Point point) {
|
||||
return String.format(Locale.ENGLISH, "\"%s\":{\"lat\":%.1f,\"lon\":%.1f}", name, point.getX(), point.getY());
|
||||
}
|
||||
@@ -1016,4 +1040,10 @@ public class MappingElasticsearchConverterUnitTests {
|
||||
@Id String id;
|
||||
List<GeoPoint> locations;
|
||||
}
|
||||
|
||||
@Data
|
||||
static class EntityWithObject {
|
||||
@Id private String id;
|
||||
private Object content;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user