Skip to content

Commit aee03df

Browse files
committed
Remove defaulting for UUID and BigInteger/BigDecimal representations.
We now align with the driver recommendation to not favor a particular representation for UUID or BigInteger/BigDecimal to avoid representation changes caused by upgrades to a newer Spring Data version. We expect an explicit configuration by applications.
1 parent c1e81b7 commit aee03df

File tree

12 files changed

+160
-107
lines changed

12 files changed

+160
-107
lines changed

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

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020
import java.util.HashSet;
2121
import java.util.Set;
2222

23-
import org.bson.UuidRepresentation;
2423
import org.springframework.beans.factory.config.BeanDefinition;
2524
import org.springframework.context.annotation.Bean;
2625
import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
@@ -226,7 +225,6 @@ protected boolean autoIndexCreation() {
226225
protected MongoClientSettings mongoClientSettings() {
227226

228227
MongoClientSettings.Builder builder = MongoClientSettings.builder();
229-
builder.uuidRepresentation(UuidRepresentation.STANDARD);
230228
configureClientSettings(builder);
231229
return builder.build();
232230
}

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

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@
2323
import java.util.function.Function;
2424
import java.util.stream.Collectors;
2525

26-
import org.bson.UuidRepresentation;
2726
import org.jspecify.annotations.Nullable;
27+
2828
import org.springframework.beans.factory.config.AbstractFactoryBean;
2929
import org.springframework.dao.DataAccessException;
3030
import org.springframework.dao.support.PersistenceExceptionTranslator;
@@ -162,7 +162,6 @@ protected MongoClientSettings computeClientSetting() {
162162
getOrDefault(port, "" + ServerAddress.defaultPort())));
163163

164164
Builder builder = MongoClientSettings.builder().applyConnectionString(connectionString);
165-
builder.uuidRepresentation(UuidRepresentation.STANDARD);
166165

167166
if (mongoClientSettings != null) {
168167

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

Lines changed: 88 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,14 @@
2323
import java.net.URI;
2424
import java.net.URL;
2525
import java.time.Instant;
26+
import java.time.LocalDate;
27+
import java.time.LocalDateTime;
28+
import java.time.LocalTime;
29+
import java.time.ZoneId;
2630
import java.util.ArrayList;
2731
import java.util.Collection;
2832
import java.util.Currency;
33+
import java.util.Date;
2934
import java.util.List;
3035
import java.util.UUID;
3136
import java.util.concurrent.atomic.AtomicInteger;
@@ -83,19 +88,67 @@ abstract class MongoConverters {
8388
private MongoConverters() {}
8489

8590
/**
86-
* Returns the converters to be registered.
91+
* Returns the {@code Date} to UTC converters to be registered.
8792
*
8893
* @return
89-
* @since 1.9
94+
* @since 5.0
9095
*/
91-
static Collection<Object> getConvertersToRegister() {
96+
static Collection<Object> getDateToUtcConverters() {
9297

93-
List<Object> converters = new ArrayList<>();
98+
List<Object> converters = new ArrayList<>(3);
99+
100+
converters.add(DateToUtcLocalDateConverter.INSTANCE);
101+
converters.add(DateToUtcLocalTimeConverter.INSTANCE);
102+
converters.add(DateToUtcLocalDateTimeConverter.INSTANCE);
103+
104+
return converters;
105+
}
106+
107+
/**
108+
* Returns the {@code Decimal128} converters to be registered.
109+
*
110+
* @return
111+
* @since 5.0
112+
*/
113+
static Collection<Object> getBigNumberDecimal128Converters() {
114+
115+
List<Object> converters = new ArrayList<>(3);
94116

95117
converters.add(BigDecimalToDecimal128Converter.INSTANCE);
96118
converters.add(Decimal128ToBigDecimalConverter.INSTANCE);
97119
converters.add(BigIntegerToDecimal128Converter.INSTANCE);
98120

121+
return converters;
122+
}
123+
124+
/**
125+
* Returns the {@code String} converters to be registered for {@link BigInteger} and {@link BigDecimal}.
126+
*
127+
* @return
128+
* @since 5.0
129+
*/
130+
static Collection<Object> getBigNumberStringConverters() {
131+
132+
List<Object> converters = new ArrayList<>(4);
133+
134+
converters.add(BigDecimalToStringConverter.INSTANCE);
135+
converters.add(StringToBigDecimalConverter.INSTANCE);
136+
converters.add(BigIntegerToStringConverter.INSTANCE);
137+
converters.add(StringToBigIntegerConverter.INSTANCE);
138+
139+
return converters;
140+
}
141+
142+
/**
143+
* Returns the converters to be registered.
144+
*
145+
* @return
146+
* @since 1.9
147+
*/
148+
static Collection<Object> getConvertersToRegister() {
149+
150+
List<Object> converters = new ArrayList<>();
151+
99152
converters.add(URLToStringConverter.INSTANCE);
100153
converters.add(StringToURLConverter.INSTANCE);
101154
converters.add(DocumentToStringConverter.INSTANCE);
@@ -630,4 +683,35 @@ public Instant convert(BsonTimestamp source) {
630683
return Instant.ofEpochSecond(source.getTime(), 0);
631684
}
632685
}
686+
687+
@ReadingConverter
688+
private enum DateToUtcLocalDateTimeConverter implements Converter<Date, LocalDateTime> {
689+
690+
INSTANCE;
691+
692+
@Override
693+
public LocalDateTime convert(Date source) {
694+
return LocalDateTime.ofInstant(Instant.ofEpochMilli(source.getTime()), ZoneId.of("UTC"));
695+
}
696+
}
697+
698+
@ReadingConverter
699+
private enum DateToUtcLocalTimeConverter implements Converter<Date, LocalTime> {
700+
INSTANCE;
701+
702+
@Override
703+
public LocalTime convert(Date source) {
704+
return DateToUtcLocalDateTimeConverter.INSTANCE.convert(source).toLocalTime();
705+
}
706+
}
707+
708+
@ReadingConverter
709+
private enum DateToUtcLocalDateConverter implements Converter<Date, LocalDate> {
710+
INSTANCE;
711+
712+
@Override
713+
public LocalDate convert(Date source) {
714+
return DateToUtcLocalDateTimeConverter.INSTANCE.convert(source).toLocalDate();
715+
}
716+
}
633717
}

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

Lines changed: 22 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
*/
1616
package org.springframework.data.mongodb.core.convert;
1717

18-
import java.time.Instant;
1918
import java.time.LocalDate;
2019
import java.time.LocalDateTime;
2120
import java.time.LocalTime;
@@ -33,6 +32,7 @@
3332
import java.util.function.Consumer;
3433

3534
import org.jspecify.annotations.Nullable;
35+
3636
import org.springframework.core.convert.TypeDescriptor;
3737
import org.springframework.core.convert.converter.Converter;
3838
import org.springframework.core.convert.converter.ConverterFactory;
@@ -42,14 +42,9 @@
4242
import org.springframework.data.convert.PropertyValueConverter;
4343
import org.springframework.data.convert.PropertyValueConverterFactory;
4444
import org.springframework.data.convert.PropertyValueConverterRegistrar;
45-
import org.springframework.data.convert.ReadingConverter;
4645
import org.springframework.data.convert.SimplePropertyValueConversions;
4746
import org.springframework.data.convert.WritingConverter;
4847
import org.springframework.data.mapping.model.SimpleTypeHolder;
49-
import org.springframework.data.mongodb.core.convert.MongoConverters.BigDecimalToStringConverter;
50-
import org.springframework.data.mongodb.core.convert.MongoConverters.BigIntegerToStringConverter;
51-
import org.springframework.data.mongodb.core.convert.MongoConverters.StringToBigDecimalConverter;
52-
import org.springframework.data.mongodb.core.convert.MongoConverters.StringToBigIntegerConverter;
5348
import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty;
5449
import org.springframework.data.mongodb.core.mapping.MongoSimpleTypes;
5550
import org.springframework.lang.Contract;
@@ -68,7 +63,6 @@
6863
*/
6964
public class MongoCustomConversions extends org.springframework.data.convert.CustomConversions {
7065

71-
private static final StoreConversions STORE_CONVERSIONS;
7266
private static final List<Object> STORE_CONVERTERS;
7367

7468
static {
@@ -80,7 +74,6 @@ public class MongoCustomConversions extends org.springframework.data.convert.Cus
8074
converters.addAll(GeoConverters.getConvertersToRegister());
8175

8276
STORE_CONVERTERS = Collections.unmodifiableList(converters);
83-
STORE_CONVERSIONS = StoreConversions.of(MongoSimpleTypes.HOLDER, STORE_CONVERTERS);
8477
}
8578

8679
/**
@@ -156,7 +149,8 @@ public static class MongoConverterConfigurationAdapter {
156149
* List of {@literal java.time} types having different representation when rendered via the native
157150
* {@link org.bson.codecs.Codec} than the Spring Data {@link Converter}.
158151
*/
159-
private static final Set<Class<?>> JAVA_DRIVER_TIME_SIMPLE_TYPES = Set.of(LocalDate.class, LocalTime.class, LocalDateTime.class);
152+
private static final Set<Class<?>> JAVA_DRIVER_TIME_SIMPLE_TYPES = Set.of(LocalDate.class, LocalTime.class,
153+
LocalDateTime.class);
160154

161155
private boolean useNativeDriverJavaTimeCodecs = false;
162156
private BigDecimalRepresentation bigDecimals = BigDecimalRepresentation.DECIMAL128;
@@ -326,6 +320,7 @@ public MongoConverterConfigurationAdapter bigDecimal(BigDecimalRepresentation re
326320
this.bigDecimals = representation;
327321
return this;
328322
}
323+
329324
/**
330325
* Optionally set the {@link PropertyValueConversions} to be applied during mapping.
331326
* <p>
@@ -375,72 +370,40 @@ ConverterConfiguration createConverterConfiguration() {
375370
svc.init();
376371
}
377372

378-
List<Object> converters = new ArrayList<>(STORE_CONVERTERS.size() + 7);
373+
List<Object> storeConverters = new ArrayList<>(STORE_CONVERTERS.size() + 10);
379374

380375
if (bigDecimals == BigDecimalRepresentation.STRING) {
381-
382-
converters.add(BigDecimalToStringConverter.INSTANCE);
383-
converters.add(StringToBigDecimalConverter.INSTANCE);
384-
converters.add(BigIntegerToStringConverter.INSTANCE);
385-
converters.add(StringToBigIntegerConverter.INSTANCE);
376+
storeConverters.addAll(MongoConverters.getBigNumberStringConverters());
386377
}
387378

388-
if (!useNativeDriverJavaTimeCodecs) {
389-
390-
converters.addAll(customConverters);
391-
return new ConverterConfiguration(STORE_CONVERSIONS, converters, convertiblePair -> true,
392-
this.propertyValueConversions);
379+
if (bigDecimals == BigDecimalRepresentation.DECIMAL128) {
380+
storeConverters.addAll(MongoConverters.getBigNumberDecimal128Converters());
393381
}
394382

395-
/*
396-
* We need to have those converters using UTC as the default ones would go on with the systemDefault.
397-
*/
398-
converters.add(DateToUtcLocalDateConverter.INSTANCE);
399-
converters.add(DateToUtcLocalTimeConverter.INSTANCE);
400-
converters.add(DateToUtcLocalDateTimeConverter.INSTANCE);
401-
converters.addAll(STORE_CONVERTERS);
383+
if (useNativeDriverJavaTimeCodecs) {
402384

403-
StoreConversions storeConversions = StoreConversions
404-
.of(new SimpleTypeHolder(JAVA_DRIVER_TIME_SIMPLE_TYPES, MongoSimpleTypes.HOLDER), converters);
385+
/*
386+
* We need to have those converters using UTC as the default ones would go on with the systemDefault.
387+
*/
388+
storeConverters.addAll(MongoConverters.getDateToUtcConverters());
389+
storeConverters.addAll(STORE_CONVERTERS);
405390

406-
return new ConverterConfiguration(storeConversions, this.customConverters, convertiblePair -> {
391+
StoreConversions storeConversions = StoreConversions
392+
.of(new SimpleTypeHolder(JAVA_DRIVER_TIME_SIMPLE_TYPES, MongoSimpleTypes.HOLDER), storeConverters);
407393

408-
// Avoid default registrations
394+
return new ConverterConfiguration(storeConversions, this.customConverters, convertiblePair -> {
395+
396+
// Avoid default registrations
409397

410398
return !JAVA_DRIVER_TIME_SIMPLE_TYPES.contains(convertiblePair.getSourceType())
411399
|| !Date.class.isAssignableFrom(convertiblePair.getTargetType());
412400
}, this.propertyValueConversions);
413-
}
414-
415-
@ReadingConverter
416-
private enum DateToUtcLocalDateTimeConverter implements Converter<Date, LocalDateTime> {
417-
418-
INSTANCE;
419401

420-
@Override
421-
public LocalDateTime convert(Date source) {
422-
return LocalDateTime.ofInstant(Instant.ofEpochMilli(source.getTime()), ZoneId.of("UTC"));
423402
}
424-
}
425-
426-
@ReadingConverter
427-
private enum DateToUtcLocalTimeConverter implements Converter<Date, LocalTime> {
428-
INSTANCE;
429403

430-
@Override
431-
public LocalTime convert(Date source) {
432-
return DateToUtcLocalDateTimeConverter.INSTANCE.convert(source).toLocalTime();
433-
}
434-
}
435-
436-
@ReadingConverter
437-
private enum DateToUtcLocalDateConverter implements Converter<Date, LocalDate> {
438-
INSTANCE;
439-
440-
@Override
441-
public LocalDate convert(Date source) {
442-
return DateToUtcLocalDateTimeConverter.INSTANCE.convert(source).toLocalDate();
443-
}
404+
storeConverters.addAll(STORE_CONVERTERS);
405+
return new ConverterConfiguration(StoreConversions.of(MongoSimpleTypes.createSimpleTypeHolder(), storeConverters),
406+
this.customConverters, convertiblePair -> true, this.propertyValueConversions);
444407
}
445408

446409
private boolean hasDefaultPropertyValueConversions() {

spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/MongoSimpleTypes.java

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -62,22 +62,27 @@ public abstract class MongoSimpleTypes {
6262
BsonTimestamp.class, Geometry.class, GeometryCollection.class, LineString.class, MultiLineString.class,
6363
MultiPoint.class, MultiPolygon.class, Point.class, Polygon.class);
6464

65-
public static final SimpleTypeHolder HOLDER = new SimpleTypeHolder(MONGO_SIMPLE_TYPES, true) {
65+
public static final SimpleTypeHolder HOLDER = createSimpleTypeHolder();
6666

67-
@Override
68-
public boolean isSimpleType(Class<?> type) {
67+
public static SimpleTypeHolder createSimpleTypeHolder() {
6968

70-
if (type.isEnum()) {
71-
return true;
72-
}
69+
return new SimpleTypeHolder(MONGO_SIMPLE_TYPES, true) {
7370

74-
if (type.getName().startsWith("java.time")) {
75-
return false;
76-
}
71+
@Override
72+
public boolean isSimpleType(Class<?> type) {
73+
74+
if (type.isEnum()) {
75+
return true;
76+
}
7777

78-
return super.isSimpleType(type);
79-
}
80-
};
78+
if (type.getName().startsWith("java.time")) {
79+
return false;
80+
}
81+
82+
return super.isSimpleType(type);
83+
}
84+
};
85+
}
8186

8287
private MongoSimpleTypes() {}
8388
}

spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/AotPersonRepositoryIntegrationTests.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
import org.junit.jupiter.api.Disabled;
1919
import org.junit.jupiter.api.Test;
20+
2021
import org.springframework.context.ApplicationContext;
2122
import org.springframework.context.annotation.Bean;
2223
import org.springframework.context.annotation.Configuration;

spring-data-mongodb/src/test/resources/org/springframework/data/mongodb/config/MongoClientNamespaceTests-context.xml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,8 @@
33
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
44
xmlns:mongo="http://www.springframework.org/schema/data/mongo"
55
xmlns:context="http://www.springframework.org/schema/context"
6-
xmlns:util="http://www.springframework.org/schema/util"
76
xsi:schemaLocation="http://www.springframework.org/schema/data/mongo https://www.springframework.org/schema/data/mongo/spring-mongo.xsd
87
http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
9-
http://www.springframework.org/schema/util https://www.springframework.org/schema/util/spring-util.xsd
108
http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
119

1210
<context:property-placeholder

0 commit comments

Comments
 (0)