From 247f30143b61a7a9206ce55b7848e05160fb392e Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Mon, 7 May 2018 15:43:46 +0200 Subject: [PATCH] DATAMONGO-1943 - Fix ClassCastException caused by SpringDataMongodbSerializer. We now convert List-typed predicates to List to BasicDBList to meet MongodbSerializer's expectations for top-level lists used for the $and operator. Original pull request: #556. --- .../support/SpringDataMongodbSerializer.java | 29 +++++++++++++++++-- .../SpringDataMongodbSerializerUnitTests.java | 12 ++++++++ 2 files changed, 39 insertions(+), 2 deletions(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/SpringDataMongodbSerializer.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/SpringDataMongodbSerializer.java index 83f850fe5..49287b402 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/SpringDataMongodbSerializer.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/SpringDataMongodbSerializer.java @@ -17,6 +17,7 @@ package org.springframework.data.mongodb.repository.support; import java.util.Collections; import java.util.HashSet; +import java.util.List; import java.util.Optional; import java.util.Set; import java.util.regex.Pattern; @@ -27,10 +28,12 @@ import org.springframework.data.mongodb.core.convert.MongoConverter; import org.springframework.data.mongodb.core.convert.QueryMapper; import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity; import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty; +import org.springframework.data.mongodb.util.BsonUtils; import org.springframework.lang.Nullable; import org.springframework.util.Assert; import org.springframework.util.ClassUtils; +import com.mongodb.BasicDBList; import com.mongodb.BasicDBObject; import com.mongodb.DBObject; import com.mongodb.DBRef; @@ -93,7 +96,7 @@ class SpringDataMongodbSerializer extends MongodbSerializer { return super.visit(expr, context); } - return converter.convertToMongoType(expr.getConstant()); + return toQuerydslMongoType(expr.getConstant()); } /* @@ -128,7 +131,8 @@ class SpringDataMongodbSerializer extends MongodbSerializer { Document mappedIdValue = mapper.getMappedObject((BasicDBObject) superIdValue, Optional.empty()); return (DBObject) JSON.parse(mappedIdValue.toJson()); } - return super.asDBObject(key, value instanceof Pattern ? value : converter.convertToMongoType(value)); + + return super.asDBObject(key, value instanceof Pattern ? value : toQuerydslMongoType(value)); } /* @@ -231,4 +235,25 @@ class SpringDataMongodbSerializer extends MongodbSerializer { return property; } + + Object toQuerydslMongoType(Object source) { + + Object target = converter.convertToMongoType(source); + + if (target instanceof List) { + + BasicDBList newList = new BasicDBList(); + + for (Object item : (List) target) { + if (item instanceof Document) { + newList.add(new BasicDBObject(BsonUtils.asMap((Document) item))); + } else { + newList.add(item); + } + } + return newList; + } + + return target; + } } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/SpringDataMongodbSerializerUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/SpringDataMongodbSerializerUnitTests.java index 06ade013a..55faae109 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/SpringDataMongodbSerializerUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/SpringDataMongodbSerializerUnitTests.java @@ -45,6 +45,8 @@ import org.springframework.data.mongodb.repository.QPerson; import com.mongodb.BasicDBList; import com.mongodb.BasicDBObject; import com.mongodb.DBObject; +import com.mongodb.util.JSON; +import com.querydsl.core.types.dsl.BooleanExpression; import com.querydsl.core.types.dsl.BooleanOperation; import com.querydsl.core.types.dsl.PathBuilder; import com.querydsl.core.types.dsl.SimplePath; @@ -184,6 +186,16 @@ public class SpringDataMongodbSerializerUnitTests { assertThat(((DBObject) mappedPredicate).get("sex"), is((Object) "f")); } + @Test // DATAMONGO-1943 + public void shouldRemarshallListsAndDocuments() { + + BooleanExpression criteria = QPerson.person.firstname.isNotEmpty() + .and(QPerson.person.firstname.containsIgnoreCase("foo")).not(); + + assertThat(this.serializer.handle(criteria), is(equalTo(JSON.parse("{ \"$or\" : [ { \"firstname\" : { \"$ne\" : { " + + "\"$ne\" : \"\"}}} , { \"firstname\" : { \"$not\" : { \"$regex\" : \".*\\\\Qfoo\\\\E.*\" , \"$options\" : \"i\"}}}]}")))); + } + class Address { String id; String street;