Browse Source

DATAMONGO-2388 - Fix CodecConfigurationException when reading index info that contains DbRef.

Provide the default CodecRegistry when converting partial index data to its String representation used in IndexInfo.

Original pull request: #797.
2.1.x
Christoph Strobl 6 years ago committed by Mark Paluch
parent
commit
5c80ee0087
No known key found for this signature in database
GPG Key ID: 51A00FA751B91849
  1. 20
      spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/IndexInfo.java
  2. 85
      spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/BsonUtils.java
  3. 17
      spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultIndexOperationsIntegrationTests.java

20
spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/IndexInfo.java

@ -25,6 +25,7 @@ import java.util.List; @@ -25,6 +25,7 @@ import java.util.List;
import java.util.Optional;
import org.bson.Document;
import org.springframework.data.mongodb.util.BsonUtils;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;
@ -107,8 +108,8 @@ public class IndexInfo { @@ -107,8 +108,8 @@ public class IndexInfo {
boolean sparse = sourceDocument.containsKey("sparse") ? (Boolean) sourceDocument.get("sparse") : false;
String language = sourceDocument.containsKey("default_language") ? (String) sourceDocument.get("default_language")
: "";
String partialFilter = sourceDocument.containsKey("partialFilterExpression")
? ((Document) sourceDocument.get("partialFilterExpression")).toJson() : null;
String partialFilter = extractPartialFilterString(sourceDocument);
IndexInfo info = new IndexInfo(indexFields, name, unique, sparse, language);
info.partialFilterExpression = partialFilter;
@ -116,6 +117,21 @@ public class IndexInfo { @@ -116,6 +117,21 @@ public class IndexInfo {
return info;
}
/**
* @param sourceDocument
* @return the {@link String} representation of the partial filter {@link Document}.
* @since 2.1.11
*/
@Nullable
private static String extractPartialFilterString(Document sourceDocument) {
if (!sourceDocument.containsKey("partialFilterExpression")) {
return null;
}
return BsonUtils.toJson(sourceDocument.get("partialFilterExpression", Document.class));
}
/**
* Returns the individual index fields of the index.
*

85
spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/BsonUtils.java

@ -15,17 +15,27 @@ @@ -15,17 +15,27 @@
*/
package org.springframework.data.mongodb.util;
import java.util.Arrays;
import java.util.Collection;
import java.util.Date;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.StreamSupport;
import org.bson.BsonValue;
import org.bson.Document;
import org.bson.conversions.Bson;
import org.bson.json.JsonParseException;
import org.springframework.core.convert.converter.Converter;
import org.springframework.lang.Nullable;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;
import com.mongodb.DBRef;
import com.mongodb.MongoClientSettings;
/**
* @author Christoph Strobl
@ -104,4 +114,79 @@ public class BsonUtils { @@ -104,4 +114,79 @@ public class BsonUtils {
return value;
}
}
/**
* Serialize the given {@link Document} as Json applying default codecs if necessary.
*
* @param source
* @return
* @since 2.1.1
*/
@Nullable
public static String toJson(@Nullable Document source) {
if (source == null) {
return null;
}
try {
return source.toJson();
} catch (Exception e) {
return toJson((Object) source);
}
}
private static String toJson(@Nullable Object value) {
if (value == null) {
return null;
}
try {
return value instanceof Document
? ((Document) value).toJson(MongoClientSettings.getDefaultCodecRegistry().get(Document.class))
: serializeValue(value);
} catch (Exception e) {
if (value instanceof Collection) {
return toString((Collection<?>) value);
} else if (value instanceof Map) {
return toString((Map<?, ?>) value);
} else if (ObjectUtils.isArray(value)) {
return toString(Arrays.asList(ObjectUtils.toObjectArray(value)));
}
throw e instanceof JsonParseException ? (JsonParseException) e : new JsonParseException(e);
}
}
private static String serializeValue(@Nullable Object value) {
if (value == null) {
return "null";
}
String documentJson = new Document("toBeEncoded", value).toJson();
return documentJson.substring(documentJson.indexOf(':') + 1, documentJson.length() - 1).trim();
}
private static String toString(Map<?, ?> source) {
return iterableToDelimitedString(source.entrySet(), "{ ", " }",
entry -> String.format("\"%s\" : %s", entry.getKey(), toJson(entry.getValue())));
}
private static String toString(Collection<?> source) {
return iterableToDelimitedString(source, "[ ", " ]", BsonUtils::toJson);
}
private static <T> String iterableToDelimitedString(Iterable<T> source, String prefix, String postfix,
Converter<? super T, Object> transformer) {
return prefix
+ StringUtils.collectionToCommaDelimitedString(
StreamSupport.stream(source.spliterator(), false).map(transformer::convert).collect(Collectors.toList()))
+ postfix;
}
}

17
spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultIndexOperationsIntegrationTests.java

@ -21,6 +21,7 @@ import static org.junit.Assume.*; @@ -21,6 +21,7 @@ import static org.junit.Assume.*;
import static org.springframework.data.mongodb.core.index.PartialIndexFilter.*;
import static org.springframework.data.mongodb.core.query.Criteria.*;
import org.bson.BsonDocument;
import org.bson.Document;
import org.junit.Before;
import org.junit.Test;
@ -40,6 +41,7 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @@ -40,6 +41,7 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.util.ObjectUtils;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.model.IndexOptions;
/**
* Integration tests for {@link DefaultIndexOperations}.
@ -150,6 +152,21 @@ public class DefaultIndexOperationsIntegrationTests { @@ -150,6 +152,21 @@ public class DefaultIndexOperationsIntegrationTests {
assertThat(info.getPartialFilterExpression()).isEqualTo("{ \"a_g_e\" : { \"$gte\" : 10 } }");
}
@Test // DATAMONGO-2388
public void shouldReadIndexWithPartialFilterContainingDbRefCorrectly() {
BsonDocument partialFilter = BsonDocument.parse(
"{ \"the-ref\" : { \"$ref\" : \"other-collection\", \"$id\" : { \"$oid\" : \"59ce08baf264b906810fe8c5\"} } }");
IndexOptions indexOptions = new IndexOptions();
indexOptions.name("partial-with-dbref");
indexOptions.partialFilterExpression(partialFilter);
collection.createIndex(BsonDocument.parse("{ \"key-1\" : 1, \"key-2\": 1}"), indexOptions);
IndexInfo info = findAndReturnIndexInfo(indexOps.getIndexInfo(), "partial-with-dbref");
assertThat(BsonDocument.parse(info.getPartialFilterExpression())).isEqualTo(partialFilter);
}
@Test // DATAMONGO-1518
public void shouldCreateIndexWithCollationCorrectly() {

Loading…
Cancel
Save