Skip to content

Commit 6d54b25

Browse files
committed
DATAMONGO-2400 - Polishing.
Adapt to changes in commons. Add functional create method to MongoCustomConversions. Update Javadoc and reference documentation. Original pull request: #810.
1 parent 3b6880e commit 6d54b25

File tree

5 files changed

+71
-52
lines changed

5 files changed

+71
-52
lines changed

spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoConfigurationSupport.java

Lines changed: 9 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -95,33 +95,28 @@ public MongoMappingContext mongoMappingContext() throws ClassNotFoundException {
9595
* Register custom {@link Converter}s in a {@link CustomConversions} object if required. These
9696
* {@link CustomConversions} will be registered with the
9797
* {@link org.springframework.data.mongodb.core.convert.MappingMongoConverter} and {@link #mongoMappingContext()}.
98-
* Returns an empty {@link MongoCustomConversions} instance by default. <br />
99-
* <strong>NOTE:</strong> Use {@link #customConversionsConfiguration(MongoConverterConfigurationAdapter)} to configure
100-
* MongoDB native simple types and register custom {@link Converter converters}.
98+
* Returns an empty {@link MongoCustomConversions} instance by default.
99+
* <p>
100+
* <strong>NOTE:</strong> Use {@link #configureConverters(MongoConverterConfigurationAdapter)} to configure MongoDB
101+
* native simple types and register custom {@link Converter converters}.
101102
*
102103
* @return must not be {@literal null}.
103104
*/
104105
@Bean
105106
public CustomConversions customConversions() {
106-
return new MongoCustomConversions(this::customConversionsConfiguration);
107+
return MongoCustomConversions.create(this::configureConverters);
107108
}
108109

109110
/**
110111
* Configuration hook for {@link MongoCustomConversions} creation.
111112
*
112113
* @param converterConfigurationAdapter never {@literal null}.
113114
* @since 2.3
115+
* @see MongoConverterConfigurationAdapter#useNativeDriverJavaTimeCodecs()
116+
* @see MongoConverterConfigurationAdapter#useSpringDataJavaTimeCodecs()
114117
*/
115-
protected void customConversionsConfiguration(MongoConverterConfigurationAdapter converterConfigurationAdapter) {
116-
117-
/*
118-
* In case you want to use the MongoDB Java Driver native Codecs for java.time types instead of the converters SpringData
119-
* ships with, then you may want to call the following here.
120-
*
121-
* converterConfigurationAdapter.useNativeDriverJavaTimeCodecs()
122-
*
123-
* But please, be careful! LocalDate, LocalTime and LocalDateTime will be stored with different values by doing so.
124-
*/
118+
protected void configureConverters(MongoConverterConfigurationAdapter converterConfigurationAdapter) {
119+
125120
}
126121

127122
/**

spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MongoCustomConversions.java

Lines changed: 52 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -31,13 +31,11 @@
3131
import java.util.Locale;
3232
import java.util.Set;
3333
import java.util.function.Consumer;
34-
import java.util.stream.Collectors;
3534

3635
import org.springframework.core.convert.TypeDescriptor;
3736
import org.springframework.core.convert.converter.Converter;
3837
import org.springframework.core.convert.converter.ConverterFactory;
3938
import org.springframework.core.convert.converter.GenericConverter;
40-
import org.springframework.core.convert.converter.GenericConverter.ConvertiblePair;
4139
import org.springframework.data.convert.JodaTimeConverters;
4240
import org.springframework.data.convert.WritingConverter;
4341
import org.springframework.data.mapping.model.SimpleTypeHolder;
@@ -87,30 +85,33 @@ public class MongoCustomConversions extends org.springframework.data.convert.Cus
8785
* @param converters must not be {@literal null}.
8886
*/
8987
public MongoCustomConversions(List<?> converters) {
88+
this(MongoConverterConfigurationAdapter.from(converters));
89+
}
9090

91-
this(converterConfigurationAdapter -> {
92-
93-
converterConfigurationAdapter.useSpringDataJavaTimeCodecs();
94-
converterConfigurationAdapter.registerConverters(converters);
95-
});
91+
/**
92+
* Create a new {@link MongoCustomConversions} given {@link MongoConverterConfigurationAdapter}.
93+
*
94+
* @param conversionConfiguration must not be {@literal null}.
95+
* @since 2.3
96+
*/
97+
protected MongoCustomConversions(MongoConverterConfigurationAdapter conversionConfiguration) {
98+
super(conversionConfiguration.createConverterConfiguration());
9699
}
97100

98101
/**
99102
* Functional style {@link org.springframework.data.convert.CustomConversions} creation giving users a convenient way
100103
* of configuring store specific capabilities by providing deferred hooks to what will be configured when creating the
101104
* {@link org.springframework.data.convert.CustomConversions#CustomConversions(ConverterConfiguration) instance}.
102105
*
103-
* @param conversionConfiguration must not be {@literal null}.
106+
* @param configurer must not be {@literal null}.
104107
* @since 2.3
105108
*/
106-
public MongoCustomConversions(Consumer<MongoConverterConfigurationAdapter> conversionConfiguration) {
109+
public static MongoCustomConversions create(Consumer<MongoConverterConfigurationAdapter> configurer) {
107110

108-
super(() -> {
111+
MongoConverterConfigurationAdapter adapter = new MongoConverterConfigurationAdapter();
112+
configurer.accept(adapter);
109113

110-
MongoConverterConfigurationAdapter adapter = new MongoConverterConfigurationAdapter();
111-
conversionConfiguration.accept(adapter);
112-
return adapter.createConverterConfiguration();
113-
});
114+
return new MongoCustomConversions(adapter);
114115
}
115116

116117
@WritingConverter
@@ -152,14 +153,32 @@ public static class MongoConverterConfigurationAdapter {
152153
* List of {@literal java.time} types having different representation when rendered via the native
153154
* {@link org.bson.codecs.Codec} than the Spring Data {@link Converter}.
154155
*/
155-
private static final List<Class<?>> JAVA_DRIVER_TIME_SIMPLE_TYPES = Arrays.asList(LocalDate.class, LocalTime.class,
156-
LocalDateTime.class);
156+
private static final Set<Class<?>> JAVA_DRIVER_TIME_SIMPLE_TYPES = new HashSet<>(
157+
Arrays.asList(LocalDate.class, LocalTime.class, LocalDateTime.class));
157158

158159
private boolean useNativeDriverJavaTimeCodecs = false;
159-
private List<Object> customConverters = new ArrayList<>();
160+
private final List<Object> customConverters = new ArrayList<>();
160161

161162
/**
162-
* Set wether or not to use the native MongoDB Java Driver {@link org.bson.codecs.Codec codes} for
163+
* Create a {@link MongoConverterConfigurationAdapter} using the provided {@code converters} and our own codecs for
164+
* JSR-310 types.
165+
*
166+
* @param converters must not be {@literal null}.
167+
* @return
168+
*/
169+
public static MongoConverterConfigurationAdapter from(List<?> converters) {
170+
171+
Assert.notNull(converters, "Converters must not be null");
172+
173+
MongoConverterConfigurationAdapter converterConfigurationAdapter = new MongoConverterConfigurationAdapter();
174+
converterConfigurationAdapter.useSpringDataJavaTimeCodecs();
175+
converterConfigurationAdapter.registerConverters(converters);
176+
177+
return converterConfigurationAdapter;
178+
}
179+
180+
/**
181+
* Set whether or not to use the native MongoDB Java Driver {@link org.bson.codecs.Codec codes} for
163182
* {@link org.bson.codecs.jsr310.LocalDateCodec LocalDate}, {@link org.bson.codecs.jsr310.LocalTimeCodec LocalTime}
164183
* and {@link org.bson.codecs.jsr310.LocalDateTimeCodec LocalDateTime} using a {@link ZoneOffset#UTC}.
165184
*
@@ -232,7 +251,9 @@ public MongoConverterConfigurationAdapter registerConverterFactory(ConverterFact
232251
*/
233252
public MongoConverterConfigurationAdapter registerConverters(Collection<?> converters) {
234253

254+
Assert.notNull(converters, "Converters must not be null");
235255
Assert.noNullElements(converters, "Converters must not be null nor contain null values!");
256+
236257
customConverters.addAll(converters);
237258
return this;
238259
}
@@ -246,23 +267,26 @@ ConverterConfiguration createConverterConfiguration() {
246267
/*
247268
* We need to have those converters using UTC as the default ones would go on with the systemDefault.
248269
*/
249-
List<Object> converters = new ArrayList<>();
270+
List<Object> converters = new ArrayList<>(STORE_CONVERTERS.size() + 3);
250271
converters.add(DateToUtcLocalDateConverter.INSTANCE);
251272
converters.add(DateToUtcLocalTimeConverter.INSTANCE);
252273
converters.add(DateToUtcLocalDateTimeConverter.INSTANCE);
253274
converters.addAll(STORE_CONVERTERS);
254275

255-
/*
256-
* Right, good catch! We also need to make sure to remove default writing converters for java.time types.
257-
*/
258-
List<ConvertiblePair> skipConverterRegistrationFor = JAVA_DRIVER_TIME_SIMPLE_TYPES.stream() //
259-
.map(it -> new ConvertiblePair(it, Date.class)) //
260-
.collect(Collectors.toList()); //
261-
262276
StoreConversions storeConversions = StoreConversions
263-
.of(new SimpleTypeHolder(new HashSet<>(JAVA_DRIVER_TIME_SIMPLE_TYPES), MongoSimpleTypes.HOLDER), converters);
277+
.of(new SimpleTypeHolder(JAVA_DRIVER_TIME_SIMPLE_TYPES, MongoSimpleTypes.HOLDER), converters);
278+
279+
return new ConverterConfiguration(storeConversions, this.customConverters, convertiblePair -> {
280+
281+
// Avoid default registrations
282+
283+
if (JAVA_DRIVER_TIME_SIMPLE_TYPES.contains(convertiblePair.getSourceType())
284+
&& Date.class.isAssignableFrom(convertiblePair.getTargetType())) {
285+
return false;
286+
}
264287

265-
return new ConverterConfiguration(storeConversions, this.customConverters, skipConverterRegistrationFor);
288+
return true;
289+
});
266290
}
267291

268292
private enum DateToUtcLocalDateTimeConverter implements Converter<Date, LocalDateTime> {

spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterTests.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
import org.springframework.data.annotation.Id;
4040
import org.springframework.data.mongodb.MongoDatabaseFactory;
4141
import org.springframework.data.mongodb.core.SimpleMongoClientDatabaseFactory;
42+
import org.springframework.data.mongodb.core.convert.MongoCustomConversions.MongoConverterConfigurationAdapter;
4243
import org.springframework.data.mongodb.core.mapping.DBRef;
4344
import org.springframework.data.mongodb.core.mapping.MongoMappingContext;
4445
import org.springframework.data.mongodb.test.util.Client;
@@ -138,9 +139,8 @@ public void readJavaTimeValuesWrittenViaCodec() {
138139
void configureConverterWithNativeJavaTimeCodec() {
139140

140141
converter = new MappingMongoConverter(dbRefResolver, mappingContext);
141-
converter.setCustomConversions(new MongoCustomConversions(config -> {
142-
config.useNativeDriverJavaTimeCodecs();
143-
}));
142+
converter.setCustomConversions(
143+
MongoCustomConversions.create(MongoConverterConfigurationAdapter::useNativeDriverJavaTimeCodecs));
144144
converter.afterPropertiesSet();
145145
}
146146

spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterUnitTests.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1087,9 +1087,9 @@ public void writeJavaTimeValuesViaCodec() {
10871087
void configureConverterWithNativeJavaTimeCodec() {
10881088

10891089
converter = new MappingMongoConverter(resolver, mappingContext);
1090-
converter.setCustomConversions(new MongoCustomConversions(config -> {
1091-
config.useNativeDriverJavaTimeCodecs();
1092-
}));
1090+
1091+
converter.setCustomConversions(MongoCustomConversions
1092+
.create(MongoCustomConversions.MongoConverterConfigurationAdapter::useNativeDriverJavaTimeCodecs));
10931093
converter.afterPropertiesSet();
10941094
}
10951095

src/main/asciidoc/reference/mapping.adoc

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
12
[[mapping-chapter]]
23
= Mapping
34

@@ -290,10 +291,8 @@ public class GeoSpatialAppConfig extends AbstractMongoClientConfiguration {
290291
return "com.bigbank.domain";
291292
}
292293
293-
// the following are optional
294-
295294
@Override
296-
void customConversionsConfiguration(MongoConverterConfigurationAdapter adapter) {
295+
void configureConverters(MongoConverterConfigurationAdapter adapter) {
297296
298297
adapter.registerConverter(new org.springframework.data.mongodb.test.PersonReadConverter());
299298
adapter.registerConverter(new org.springframework.data.mongodb.test.PersonWriteConverter());
@@ -310,11 +309,12 @@ public class GeoSpatialAppConfig extends AbstractMongoClientConfiguration {
310309
`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.
311310

312311
You can add additional converters to the converter by overriding the `customConversionsConfiguration` method.
312+
MongoDB's native JSR-310 support can be enabled through `MongoConverterConfigurationAdapter.useNativeDriverJavaTimeCodecs()`.
313313
Also shown in the preceding example is a `LoggingEventListener`, which logs `MongoMappingEvent` instances that are posted onto Spring's `ApplicationContextEvent` infrastructure.
314314

315315
NOTE: `AbstractMongoClientConfiguration` creates a `MongoTemplate` instance and registers it with the container under the name `mongoTemplate`.
316316

317-
Spring's MongoDB namespace lets you enable mapping functionality in XML, as the following example shows:
317+
Spring's MongoDB namespace lets you enable mapping functionality in XML, as the following example shows:
318318

319319
.XML schema to configure MongoDB mapping support
320320
====

0 commit comments

Comments
 (0)