Skip to content

DATAMONGO-2388 - Fix CodecConfigurationException when reading index info containing DbRef in partial filter expression. #797

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

<groupId>org.springframework.data</groupId>
<artifactId>spring-data-mongodb-parent</artifactId>
<version>2.3.0.BUILD-SNAPSHOT</version>
<version>2.2.0.DATAMONGO-2388-SNAPSHOT</version>
<packaging>pom</packaging>

<name>Spring Data MongoDB</name>
Expand Down
2 changes: 1 addition & 1 deletion spring-data-mongodb-benchmarks/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
<parent>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-mongodb-parent</artifactId>
<version>2.3.0.BUILD-SNAPSHOT</version>
<version>2.2.0.DATAMONGO-2388-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

Expand Down
2 changes: 1 addition & 1 deletion spring-data-mongodb-distribution/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
<parent>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-mongodb-parent</artifactId>
<version>2.3.0.BUILD-SNAPSHOT</version>
<version>2.2.0.DATAMONGO-2388-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

Expand Down
2 changes: 1 addition & 1 deletion spring-data-mongodb/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
<parent>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-mongodb-parent</artifactId>
<version>2.3.0.BUILD-SNAPSHOT</version>
<version>2.2.0.DATAMONGO-2388-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
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.NumberUtils;
Expand Down Expand Up @@ -117,9 +118,8 @@ public static IndexInfo indexInfoOf(Document sourceDocument) {
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;
Expand All @@ -134,6 +134,21 @@ public static IndexInfo indexInfoOf(Document sourceDocument) {
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.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,20 +16,26 @@
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.function.Function;
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
Expand Down Expand Up @@ -147,4 +153,77 @@ public static Document toDocumentOrElse(String source, Function<String, Document
return orElse.apply(source);
}

/**
* Serialize the given {@link Document} as Json applying default codecs if necessary.
*
* @param source
* @return
* @since 2.1.1
*/
public static String toJson(Document source) {

if (source == null) {
return null;
}

try {
return source.toJson();
} catch (Exception e) {
return toJson((Object) source);
}
}

private static String toJson(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;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
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;
Expand All @@ -39,6 +40,7 @@
import org.springframework.util.ObjectUtils;

import com.mongodb.client.MongoCollection;
import com.mongodb.client.model.IndexOptions;

/**
* Integration tests for {@link DefaultIndexOperations}.
Expand Down Expand Up @@ -153,6 +155,21 @@ public void shouldFavorExplicitMappingHintViaClass() {
.isEqualTo(Document.parse("{ \"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() {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,11 @@ public MongoClient mongoClient() {
protected String getDatabaseName() {
return "collation-tests";
}

@Override
protected boolean autoIndexCreation() {
return false;
}
}

@Autowired MongoTemplate template;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,11 @@ protected String getDatabaseName() {
return DB_NAME;
}

@Override
protected boolean autoIndexCreation() {
return false;
}

@Bean
MongoTransactionManager txManager(MongoDbFactory dbFactory) {
return new MongoTransactionManager(dbFactory);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,11 @@ public MongoClient mongoClient() {
protected String getDatabaseName() {
return "validation-tests";
}

@Override
protected boolean autoIndexCreation() {
return false;
}
}

@Autowired MongoTemplate template;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,11 @@ protected String getDatabaseName() {
public MongoClient mongoClient() {
return MongoTestUtils.client();
}

@Override
protected boolean autoIndexCreation() {
return false;
}
}

@Autowired MongoOperations mongoOps;
Expand Down