diff --git a/spring-data-mongodb/pom.xml b/spring-data-mongodb/pom.xml
index 0d7fb7449..7d8e59dd5 100644
--- a/spring-data-mongodb/pom.xml
+++ b/spring-data-mongodb/pom.xml
@@ -152,6 +152,13 @@
junit
test
+
+
+ joda-time
+ joda-time
+ 1.6
+ test
+
diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/convert/SimpleMongoConverter.java b/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/convert/SimpleMongoConverter.java
index 404226d45..11661eed6 100644
--- a/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/convert/SimpleMongoConverter.java
+++ b/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/convert/SimpleMongoConverter.java
@@ -32,12 +32,9 @@ import org.bson.types.ObjectId;
import org.springframework.beans.BeanUtils;
import org.springframework.core.CollectionFactory;
import org.springframework.core.convert.ConversionFailedException;
-import org.springframework.core.convert.TypeDescriptor;
-import org.springframework.core.convert.converter.ConditionalGenericConverter;
+import org.springframework.core.convert.ConversionService;
import org.springframework.core.convert.converter.Converter;
import org.springframework.core.convert.converter.ConverterFactory;
-import org.springframework.core.convert.converter.GenericConverter;
-import org.springframework.core.convert.converter.GenericConverter.ConvertiblePair;
import org.springframework.core.convert.support.ConversionServiceFactory;
import org.springframework.core.convert.support.GenericConversionService;
import org.springframework.data.document.mongodb.MongoPropertyDescriptors.MongoPropertyDescriptor;
@@ -54,6 +51,7 @@ import org.springframework.util.comparator.CompoundComparator;
public class SimpleMongoConverter implements MongoConverter {
private static final Log LOG = LogFactory.getLog(SimpleMongoConverter.class);
+ private static final List> MONGO_TYPES = Arrays.asList(Number.class, Date.class, String.class, DBObject.class);
private static final Set SIMPLE_TYPES;
static {
@@ -112,8 +110,8 @@ public class SimpleMongoConverter implements MongoConverter {
* Creates a {@link SimpleMongoConverter}.
*/
public SimpleMongoConverter() {
- this.conversionService = new SimpleToStringSuppressingGenericConversionService();
- ConversionServiceFactory.addDefaultConverters(conversionService);
+ this.conversionService = ConversionServiceFactory.createDefaultConversionService();
+ this.conversionService.removeConvertible(Object.class, String.class);
initializeConverters();
}
@@ -123,12 +121,10 @@ public class SimpleMongoConverter implements MongoConverter {
*/
protected void initializeConverters() {
-
conversionService.addConverter(ObjectIdToStringConverter.INSTANCE);
conversionService.addConverter(StringToObjectIdConverter.INSTANCE);
conversionService.addConverter(ObjectIdToBigIntegerConverter.INSTANCE);
conversionService.addConverter(BigIntegerToIdConverter.INSTANCE);
-
}
/**
@@ -237,15 +233,32 @@ public class SimpleMongoConverter implements MongoConverter {
return;
}
- if (conversionService.canConvert(value.getClass(), String.class)) {
- dbo.put(keyToUse, conversionService.convert(value, String.class));
+ Class> customTargetType = getCustomTargetType(value);
+ if (customTargetType != null) {
+ dbo.put(keyToUse, conversionService.convert(value, customTargetType));
return;
}
DBObject nestedDbo = new BasicDBObject();
write(value, nestedDbo);
dbo.put(keyToUse, nestedDbo);
-
+ }
+
+ /**
+ * Returns whether the {@link ConversionService} has a custom {@link Converter} registered that can convert the given
+ * object into one of the types supported by MongoDB.
+ *
+ * @param obj
+ * @return
+ */
+ private Class> getCustomTargetType(Object obj) {
+
+ for (Class> mongoType : MONGO_TYPES) {
+ if (conversionService.canConvert(obj.getClass(), mongoType)) {
+ return mongoType;
+ }
+ }
+ return null;
}
/**
@@ -510,30 +523,6 @@ public class SimpleMongoConverter implements MongoConverter {
public ObjectId convertObjectId(Object id) {
return conversionService.convert(id, ObjectId.class);
}
-
- private static class SimpleToStringSuppressingGenericConversionService extends GenericConversionService {
-
- private static final Set REFERENCE = Collections.singleton(new ConvertiblePair(Object.class, String.class));
-
- /* (non-Javadoc)
- * @see org.springframework.core.convert.support.GenericConversionService#getConverter(org.springframework.core.convert.TypeDescriptor, org.springframework.core.convert.TypeDescriptor)
- */
- @Override
- protected GenericConverter getConverter(TypeDescriptor sourceType, TypeDescriptor targetType) {
-
- GenericConverter converter = super.getConverter(sourceType, targetType);
-
- if (converter instanceof ConditionalGenericConverter) {
-
- Set convertibleTypes = ((ConditionalGenericConverter) converter).getConvertibleTypes();
- if (REFERENCE.equals(convertibleTypes)) {
- return null;
- }
- }
-
- return converter;
- }
- }
/**
* Simple singleton to convert {@link ObjectId}s to their {@link String} representation.
diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/SimpleMongoConverterTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/SimpleMongoConverterTests.java
index 892f1b3e5..4ca57c3ae 100644
--- a/spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/SimpleMongoConverterTests.java
+++ b/spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/SimpleMongoConverterTests.java
@@ -21,15 +21,22 @@ import static org.junit.Assert.*;
import java.lang.reflect.Field;
import java.math.BigInteger;
import java.util.Arrays;
+import java.util.Date;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.List;
import java.util.Map;
+import java.util.Set;
import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;
import com.mongodb.util.JSON;
+
+import org.hamcrest.CoreMatchers;
+import org.joda.time.LocalDate;
import org.junit.Before;
import org.junit.Test;
+import org.springframework.core.convert.converter.Converter;
import org.springframework.data.document.mongodb.SomeEnumTest.NumberEnum;
import org.springframework.data.document.mongodb.SomeEnumTest.StringEnum;
import org.springframework.data.document.mongodb.convert.SimpleMongoConverter;
@@ -292,10 +299,50 @@ public class SimpleMongoConverterTests {
(DBObject) JSON.parse("{\"_id\" : {\"$oid\" : \"4d24809660413b687f5d323e\" }}"));
assertThat(result.getId().toString(16), is("4d24809660413b687f5d323e"));
}
+
+ @Test
+ public void convertsAddressCorrectly() {
+
+ Address address = new Address();
+ address.city = "New York";
+ address.street = "Broadway";
+
+ DBObject dbObject = new BasicDBObject();
+
+ converter.write(address, dbObject);
+
+ assertThat(dbObject.get("city").toString(), is("New York"));
+ assertThat(dbObject.get("street").toString(), is("Broadway"));
+
+ Address result = converter.read(Address.class, dbObject);
+ assertThat(result.city, is("New York"));
+ assertThat(result.street, is("Broadway"));
+ }
+
+ @Test
+ public void convertsJodaTimeTypesCorrectly() {
+
+ Set> converters = new HashSet>();
+ converters.add(new LocalDateToDateConverter());
+ converters.add(new DateToLocalDateConverter());
+
+ converter.setConverters(converters);
+
+ AnotherPerson person = new AnotherPerson();
+ person.birthDate = new LocalDate();
+
+ DBObject dbObject = new BasicDBObject();
+ converter.write(person, dbObject);
+
+ assertTrue(dbObject.get("birthDate") instanceof Date);
+
+ AnotherPerson result = converter.read(AnotherPerson.class, dbObject);
+ assertThat(result.getBirthDate(), is(notNullValue()));
+ }
private void assertListOfStringAndLong(List> types) {
- assertThat(types.size(), is(2));
+ assertThat(types.size(), CoreMatchers.is(2));
assertEquals(String.class, types.get(0));
assertEquals(Long.class, types.get(1));
}
@@ -347,4 +394,39 @@ public class SimpleMongoConverterTests {
return id;
}
}
+
+ public static class Address {
+ String street;
+ String city;
+
+ public String getStreet() {
+ return street;
+ }
+
+ public String getCity() {
+ return city;
+ }
+ }
+
+ public static class AnotherPerson {
+ LocalDate birthDate;
+
+ public LocalDate getBirthDate() {
+ return birthDate;
+ }
+ }
+
+ private class LocalDateToDateConverter implements Converter {
+
+ public Date convert(LocalDate source) {
+ return source.toDateMidnight().toDate();
+ }
+ }
+
+ private class DateToLocalDateConverter implements Converter {
+
+ public LocalDate convert(Date source) {
+ return new LocalDate(source.getTime());
+ }
+ }
}