DATAMONGO-462 - Added custom converters for URL.
So far URL instances were treated as entities and serialized as nested document. As there was no custom converter registered to re-instantiate the objects and URL does not contain a no-arg constructor, reading the instances back in resulted in an ugly exception in ReflectionEntityInstantiator. We now register a custom Converter to serialize URL instances as their plain toString() representation. This causes the reading working out of the box as the StringToObjectConverter registered by default uses the constructor taking a String on URL accidentally. To make sure this still works we added an explicit StringToURLConverter to implement symmetric conversions.
This commit is contained in:
@@ -38,6 +38,8 @@ import org.springframework.data.mongodb.core.convert.MongoConverters.BigDecimalT
|
||||
import org.springframework.data.mongodb.core.convert.MongoConverters.BigIntegerToStringConverter;
|
||||
import org.springframework.data.mongodb.core.convert.MongoConverters.StringToBigDecimalConverter;
|
||||
import org.springframework.data.mongodb.core.convert.MongoConverters.StringToBigIntegerConverter;
|
||||
import org.springframework.data.mongodb.core.convert.MongoConverters.StringToURLConverter;
|
||||
import org.springframework.data.mongodb.core.convert.MongoConverters.URLToStringConverter;
|
||||
import org.springframework.data.mongodb.core.mapping.MongoSimpleTypes;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
@@ -89,6 +91,8 @@ public class CustomConversions {
|
||||
this.converters.add(StringToBigDecimalConverter.INSTANCE);
|
||||
this.converters.add(BigIntegerToStringConverter.INSTANCE);
|
||||
this.converters.add(StringToBigIntegerConverter.INSTANCE);
|
||||
this.converters.add(URLToStringConverter.INSTANCE);
|
||||
this.converters.add(StringToURLConverter.INSTANCE);
|
||||
this.converters.addAll(converters);
|
||||
|
||||
for (Object c : this.converters) {
|
||||
|
||||
@@ -17,8 +17,12 @@ package org.springframework.data.mongodb.core.convert;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.BigInteger;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
|
||||
import org.bson.types.ObjectId;
|
||||
import org.springframework.core.convert.ConversionFailedException;
|
||||
import org.springframework.core.convert.TypeDescriptor;
|
||||
import org.springframework.core.convert.converter.Converter;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
@@ -119,4 +123,28 @@ abstract class MongoConverters {
|
||||
return StringUtils.hasText(source) ? new BigInteger(source) : null;
|
||||
}
|
||||
}
|
||||
|
||||
public static enum URLToStringConverter implements Converter<URL, String> {
|
||||
INSTANCE;
|
||||
|
||||
public String convert(URL source) {
|
||||
return source == null ? null : source.toString();
|
||||
}
|
||||
}
|
||||
|
||||
public static enum StringToURLConverter implements Converter<String, URL> {
|
||||
INSTANCE;
|
||||
|
||||
private static final TypeDescriptor SOURCE = TypeDescriptor.valueOf(String.class);
|
||||
private static final TypeDescriptor TARGET = TypeDescriptor.valueOf(URL.class);
|
||||
|
||||
public URL convert(String source) {
|
||||
|
||||
try {
|
||||
return source == null ? null : new URL(source);
|
||||
} catch (MalformedURLException e) {
|
||||
throw new ConversionFailedException(SOURCE, TARGET, source, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package org.springframework.data.mongodb.core.convert;
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.net.URL;
|
||||
import java.text.DateFormat;
|
||||
import java.text.Format;
|
||||
import java.util.Arrays;
|
||||
@@ -152,6 +153,25 @@ public class CustomConversionsUnitTests {
|
||||
assertThat(conversions.isSimpleType(Binary.class), is(true));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-462
|
||||
*/
|
||||
@Test
|
||||
public void hasWriteConverterForURL() {
|
||||
|
||||
CustomConversions conversions = new CustomConversions();
|
||||
assertThat(conversions.hasCustomWriteTarget(URL.class), is(true));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-462
|
||||
*/
|
||||
@Test
|
||||
public void readTargetForURL() {
|
||||
CustomConversions conversions = new CustomConversions();
|
||||
assertThat(conversions.hasCustomReadTarget(String.class, URL.class), is(true));
|
||||
}
|
||||
|
||||
enum FormatToStringConverter implements Converter<Format, String> {
|
||||
INSTANCE;
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@ import static org.junit.Assert.*;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.BigInteger;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
@@ -1034,6 +1035,30 @@ public class MappingMongoConverterUnitTests {
|
||||
assertThat(readResult.iterator().next(), is(Map.class));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-462
|
||||
*/
|
||||
@Test
|
||||
public void readsURLsAsStringsByDefault() throws Exception {
|
||||
DBObject dbObject = new BasicDBObject("url", new URL("http://springsource.org"));
|
||||
URLWrapper result = converter.read(URLWrapper.class, dbObject);
|
||||
assertThat(result.url, is(new URL("http://springsource.org")));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-462
|
||||
*/
|
||||
@Test
|
||||
public void writesURLsAsStringsByDefault() throws Exception {
|
||||
|
||||
URLWrapper wrapper = new URLWrapper();
|
||||
wrapper.url = new URL("http://springsource.org");
|
||||
DBObject sink = new BasicDBObject();
|
||||
|
||||
converter.write(wrapper, sink);
|
||||
assertThat(sink.get("url"), is((Object) "http://springsource.org"));
|
||||
}
|
||||
|
||||
static class GenericType<T> {
|
||||
T content;
|
||||
}
|
||||
@@ -1165,6 +1190,10 @@ public class MappingMongoConverterUnitTests {
|
||||
Object value;
|
||||
}
|
||||
|
||||
static class URLWrapper {
|
||||
URL url;
|
||||
}
|
||||
|
||||
private class LocalDateToDateConverter implements Converter<LocalDate, Date> {
|
||||
|
||||
public Date convert(LocalDate source) {
|
||||
|
||||
Reference in New Issue
Block a user