DATAMONGO-2400 - Polishing.
Adapt to changes in commons. Add functional create method to MongoCustomConversions. Update Javadoc and reference documentation. Truncate precision for Java 11 build compatibility in tests. Original pull request: #810.
This commit is contained in:
@@ -95,15 +95,16 @@ public abstract class MongoConfigurationSupport {
|
||||
* Register custom {@link Converter}s in a {@link CustomConversions} object if required. These
|
||||
* {@link CustomConversions} will be registered with the
|
||||
* {@link org.springframework.data.mongodb.core.convert.MappingMongoConverter} and {@link #mongoMappingContext()}.
|
||||
* Returns an empty {@link MongoCustomConversions} instance by default. <br />
|
||||
* <strong>NOTE:</strong> Use {@link #customConversionsConfiguration(MongoConverterConfigurationAdapter)} to configure
|
||||
* MongoDB native simple types and register custom {@link Converter converters}.
|
||||
* Returns an empty {@link MongoCustomConversions} instance by default.
|
||||
* <p>
|
||||
* <strong>NOTE:</strong> Use {@link #configureConverters(MongoConverterConfigurationAdapter)} to configure MongoDB
|
||||
* native simple types and register custom {@link Converter converters}.
|
||||
*
|
||||
* @return must not be {@literal null}.
|
||||
*/
|
||||
@Bean
|
||||
public CustomConversions customConversions() {
|
||||
return new MongoCustomConversions(this::customConversionsConfiguration);
|
||||
return MongoCustomConversions.create(this::configureConverters);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -111,17 +112,11 @@ public abstract class MongoConfigurationSupport {
|
||||
*
|
||||
* @param converterConfigurationAdapter never {@literal null}.
|
||||
* @since 2.3
|
||||
* @see MongoConverterConfigurationAdapter#useNativeDriverJavaTimeCodecs()
|
||||
* @see MongoConverterConfigurationAdapter#useSpringDataJavaTimeCodecs()
|
||||
*/
|
||||
protected void customConversionsConfiguration(MongoConverterConfigurationAdapter converterConfigurationAdapter) {
|
||||
protected void configureConverters(MongoConverterConfigurationAdapter converterConfigurationAdapter) {
|
||||
|
||||
/*
|
||||
* In case you want to use the MongoDB Java Driver native Codecs for java.time types instead of the converters SpringData
|
||||
* ships with, then you may want to call the following here.
|
||||
*
|
||||
* converterConfigurationAdapter.useNativeDriverJavaTimeCodecs()
|
||||
*
|
||||
* But please, be careful! LocalDate, LocalTime and LocalDateTime will be stored with different values by doing so.
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -31,13 +31,11 @@ import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Set;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.springframework.core.convert.TypeDescriptor;
|
||||
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.data.convert.JodaTimeConverters;
|
||||
import org.springframework.data.convert.WritingConverter;
|
||||
import org.springframework.data.mapping.model.SimpleTypeHolder;
|
||||
@@ -87,12 +85,17 @@ public class MongoCustomConversions extends org.springframework.data.convert.Cus
|
||||
* @param converters must not be {@literal null}.
|
||||
*/
|
||||
public MongoCustomConversions(List<?> converters) {
|
||||
this(MongoConverterConfigurationAdapter.from(converters));
|
||||
}
|
||||
|
||||
this(converterConfigurationAdapter -> {
|
||||
|
||||
converterConfigurationAdapter.useSpringDataJavaTimeCodecs();
|
||||
converterConfigurationAdapter.registerConverters(converters);
|
||||
});
|
||||
/**
|
||||
* Create a new {@link MongoCustomConversions} given {@link MongoConverterConfigurationAdapter}.
|
||||
*
|
||||
* @param conversionConfiguration must not be {@literal null}.
|
||||
* @since 2.3
|
||||
*/
|
||||
protected MongoCustomConversions(MongoConverterConfigurationAdapter conversionConfiguration) {
|
||||
super(conversionConfiguration.createConverterConfiguration());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -100,17 +103,15 @@ public class MongoCustomConversions extends org.springframework.data.convert.Cus
|
||||
* of configuring store specific capabilities by providing deferred hooks to what will be configured when creating the
|
||||
* {@link org.springframework.data.convert.CustomConversions#CustomConversions(ConverterConfiguration) instance}.
|
||||
*
|
||||
* @param conversionConfiguration must not be {@literal null}.
|
||||
* @param configurer must not be {@literal null}.
|
||||
* @since 2.3
|
||||
*/
|
||||
public MongoCustomConversions(Consumer<MongoConverterConfigurationAdapter> conversionConfiguration) {
|
||||
public static MongoCustomConversions create(Consumer<MongoConverterConfigurationAdapter> configurer) {
|
||||
|
||||
super(() -> {
|
||||
MongoConverterConfigurationAdapter adapter = new MongoConverterConfigurationAdapter();
|
||||
configurer.accept(adapter);
|
||||
|
||||
MongoConverterConfigurationAdapter adapter = new MongoConverterConfigurationAdapter();
|
||||
conversionConfiguration.accept(adapter);
|
||||
return adapter.createConverterConfiguration();
|
||||
});
|
||||
return new MongoCustomConversions(adapter);
|
||||
}
|
||||
|
||||
@WritingConverter
|
||||
@@ -152,14 +153,32 @@ public class MongoCustomConversions extends org.springframework.data.convert.Cus
|
||||
* List of {@literal java.time} types having different representation when rendered via the native
|
||||
* {@link org.bson.codecs.Codec} than the Spring Data {@link Converter}.
|
||||
*/
|
||||
private static final List<Class<?>> JAVA_DRIVER_TIME_SIMPLE_TYPES = Arrays.asList(LocalDate.class, LocalTime.class,
|
||||
LocalDateTime.class);
|
||||
private static final Set<Class<?>> JAVA_DRIVER_TIME_SIMPLE_TYPES = new HashSet<>(
|
||||
Arrays.asList(LocalDate.class, LocalTime.class, LocalDateTime.class));
|
||||
|
||||
private boolean useNativeDriverJavaTimeCodecs = false;
|
||||
private List<Object> customConverters = new ArrayList<>();
|
||||
private final List<Object> customConverters = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* Set wether or not to use the native MongoDB Java Driver {@link org.bson.codecs.Codec codes} for
|
||||
* Create a {@link MongoConverterConfigurationAdapter} using the provided {@code converters} and our own codecs for
|
||||
* JSR-310 types.
|
||||
*
|
||||
* @param converters must not be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
public static MongoConverterConfigurationAdapter from(List<?> converters) {
|
||||
|
||||
Assert.notNull(converters, "Converters must not be null");
|
||||
|
||||
MongoConverterConfigurationAdapter converterConfigurationAdapter = new MongoConverterConfigurationAdapter();
|
||||
converterConfigurationAdapter.useSpringDataJavaTimeCodecs();
|
||||
converterConfigurationAdapter.registerConverters(converters);
|
||||
|
||||
return converterConfigurationAdapter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether or not to use the native MongoDB Java Driver {@link org.bson.codecs.Codec codes} for
|
||||
* {@link org.bson.codecs.jsr310.LocalDateCodec LocalDate}, {@link org.bson.codecs.jsr310.LocalTimeCodec LocalTime}
|
||||
* and {@link org.bson.codecs.jsr310.LocalDateTimeCodec LocalDateTime} using a {@link ZoneOffset#UTC}.
|
||||
*
|
||||
@@ -232,7 +251,9 @@ public class MongoCustomConversions extends org.springframework.data.convert.Cus
|
||||
*/
|
||||
public MongoConverterConfigurationAdapter registerConverters(Collection<?> converters) {
|
||||
|
||||
Assert.notNull(converters, "Converters must not be null");
|
||||
Assert.noNullElements(converters, "Converters must not be null nor contain null values!");
|
||||
|
||||
customConverters.addAll(converters);
|
||||
return this;
|
||||
}
|
||||
@@ -246,23 +267,26 @@ public class MongoCustomConversions extends org.springframework.data.convert.Cus
|
||||
/*
|
||||
* We need to have those converters using UTC as the default ones would go on with the systemDefault.
|
||||
*/
|
||||
List<Object> converters = new ArrayList<>();
|
||||
List<Object> converters = new ArrayList<>(STORE_CONVERTERS.size() + 3);
|
||||
converters.add(DateToUtcLocalDateConverter.INSTANCE);
|
||||
converters.add(DateToUtcLocalTimeConverter.INSTANCE);
|
||||
converters.add(DateToUtcLocalDateTimeConverter.INSTANCE);
|
||||
converters.addAll(STORE_CONVERTERS);
|
||||
|
||||
/*
|
||||
* Right, good catch! We also need to make sure to remove default writing converters for java.time types.
|
||||
*/
|
||||
List<ConvertiblePair> skipConverterRegistrationFor = JAVA_DRIVER_TIME_SIMPLE_TYPES.stream() //
|
||||
.map(it -> new ConvertiblePair(it, Date.class)) //
|
||||
.collect(Collectors.toList()); //
|
||||
|
||||
StoreConversions storeConversions = StoreConversions
|
||||
.of(new SimpleTypeHolder(new HashSet<>(JAVA_DRIVER_TIME_SIMPLE_TYPES), MongoSimpleTypes.HOLDER), converters);
|
||||
.of(new SimpleTypeHolder(JAVA_DRIVER_TIME_SIMPLE_TYPES, MongoSimpleTypes.HOLDER), converters);
|
||||
|
||||
return new ConverterConfiguration(storeConversions, this.customConverters, skipConverterRegistrationFor);
|
||||
return new ConverterConfiguration(storeConversions, this.customConverters, convertiblePair -> {
|
||||
|
||||
// Avoid default registrations
|
||||
|
||||
if (JAVA_DRIVER_TIME_SIMPLE_TYPES.contains(convertiblePair.getSourceType())
|
||||
&& Date.class.isAssignableFrom(convertiblePair.getTargetType())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
private enum DateToUtcLocalDateTimeConverter implements Converter<Date, LocalDateTime> {
|
||||
|
||||
@@ -29,6 +29,7 @@ import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.LocalTime;
|
||||
import java.time.ZoneId;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
@@ -39,6 +40,7 @@ import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.mongodb.MongoDatabaseFactory;
|
||||
import org.springframework.data.mongodb.core.SimpleMongoClientDatabaseFactory;
|
||||
import org.springframework.data.mongodb.core.convert.MongoCustomConversions.MongoConverterConfigurationAdapter;
|
||||
import org.springframework.data.mongodb.core.mapping.DBRef;
|
||||
import org.springframework.data.mongodb.core.mapping.MongoMappingContext;
|
||||
import org.springframework.data.mongodb.test.util.Client;
|
||||
@@ -125,7 +127,7 @@ public class MappingMongoConverterTests {
|
||||
configureConverterWithNativeJavaTimeCodec();
|
||||
MongoCollection<Document> mongoCollection = client.getDatabase(DATABASE).getCollection("java-time-types");
|
||||
|
||||
Instant now = Instant.now();
|
||||
Instant now = Instant.now().truncatedTo(ChronoUnit.MILLIS);
|
||||
WithJavaTimeTypes source = WithJavaTimeTypes.withJavaTimeTypes(now);
|
||||
source.id = "id-1";
|
||||
|
||||
@@ -138,9 +140,8 @@ public class MappingMongoConverterTests {
|
||||
void configureConverterWithNativeJavaTimeCodec() {
|
||||
|
||||
converter = new MappingMongoConverter(dbRefResolver, mappingContext);
|
||||
converter.setCustomConversions(new MongoCustomConversions(config -> {
|
||||
config.useNativeDriverJavaTimeCodecs();
|
||||
}));
|
||||
converter.setCustomConversions(
|
||||
MongoCustomConversions.create(MongoConverterConfigurationAdapter::useNativeDriverJavaTimeCodecs));
|
||||
converter.afterPropertiesSet();
|
||||
}
|
||||
|
||||
|
||||
@@ -1087,9 +1087,9 @@ public class MappingMongoConverterUnitTests {
|
||||
void configureConverterWithNativeJavaTimeCodec() {
|
||||
|
||||
converter = new MappingMongoConverter(resolver, mappingContext);
|
||||
converter.setCustomConversions(new MongoCustomConversions(config -> {
|
||||
config.useNativeDriverJavaTimeCodecs();
|
||||
}));
|
||||
|
||||
converter.setCustomConversions(MongoCustomConversions
|
||||
.create(MongoCustomConversions.MongoConverterConfigurationAdapter::useNativeDriverJavaTimeCodecs));
|
||||
converter.afterPropertiesSet();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
|
||||
[[mapping-chapter]]
|
||||
= Mapping
|
||||
|
||||
@@ -290,10 +291,8 @@ public class GeoSpatialAppConfig extends AbstractMongoClientConfiguration {
|
||||
return "com.bigbank.domain";
|
||||
}
|
||||
|
||||
// the following are optional
|
||||
|
||||
@Override
|
||||
void customConversionsConfiguration(MongoConverterConfigurationAdapter adapter) {
|
||||
void configureConverters(MongoConverterConfigurationAdapter adapter) {
|
||||
|
||||
adapter.registerConverter(new org.springframework.data.mongodb.test.PersonReadConverter());
|
||||
adapter.registerConverter(new org.springframework.data.mongodb.test.PersonWriteConverter());
|
||||
@@ -310,11 +309,12 @@ public class GeoSpatialAppConfig extends AbstractMongoClientConfiguration {
|
||||
`AbstractMongoClientConfiguration` requires you to implement methods that define a `com.mongodb.client.MongoClient` as well as provide a database name. `AbstractMongoClientConfiguration` also has a method named `getMappingBasePackage(…)` that you can override to tell the converter where to scan for classes annotated with the `@Document` annotation.
|
||||
|
||||
You can add additional converters to the converter by overriding the `customConversionsConfiguration` method.
|
||||
MongoDB's native JSR-310 support can be enabled through `MongoConverterConfigurationAdapter.useNativeDriverJavaTimeCodecs()`.
|
||||
Also shown in the preceding example is a `LoggingEventListener`, which logs `MongoMappingEvent` instances that are posted onto Spring's `ApplicationContextEvent` infrastructure.
|
||||
|
||||
NOTE: `AbstractMongoClientConfiguration` creates a `MongoTemplate` instance and registers it with the container under the name `mongoTemplate`.
|
||||
|
||||
Spring's MongoDB namespace lets you enable mapping functionality in XML, as the following example shows:
|
||||
Spring's MongoDB namespace lets you enable mapping functionality in XML, as the following example shows:
|
||||
|
||||
.XML schema to configure MongoDB mapping support
|
||||
====
|
||||
|
||||
Reference in New Issue
Block a user