Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

<groupId>org.springframework.data</groupId>
<artifactId>spring-data-mongodb-parent</artifactId>
<version>5.0.0-SNAPSHOT</version>
<version>5.0.0-GH-5037-SNAPSHOT</version>
<packaging>pom</packaging>

<name>Spring Data MongoDB</name>
Expand Down
2 changes: 1 addition & 1 deletion spring-data-mongodb-distribution/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
<parent>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-mongodb-parent</artifactId>
<version>5.0.0-SNAPSHOT</version>
<version>5.0.0-GH-5037-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

Expand Down
2 changes: 1 addition & 1 deletion spring-data-mongodb/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
<parent>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-mongodb-parent</artifactId>
<version>5.0.0-SNAPSHOT</version>
<version>5.0.0-GH-5037-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
import java.util.HashSet;
import java.util.Set;

import org.bson.UuidRepresentation;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
Expand Down Expand Up @@ -226,7 +225,6 @@ protected boolean autoIndexCreation() {
protected MongoClientSettings mongoClientSettings() {

MongoClientSettings.Builder builder = MongoClientSettings.builder();
builder.uuidRepresentation(UuidRepresentation.STANDARD);
configureClientSettings(builder);
return builder.build();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@
import java.util.function.Function;
import java.util.stream.Collectors;

import org.bson.UuidRepresentation;
import org.jspecify.annotations.Nullable;

import org.springframework.beans.factory.config.AbstractFactoryBean;
import org.springframework.dao.DataAccessException;
import org.springframework.dao.support.PersistenceExceptionTranslator;
Expand Down Expand Up @@ -162,7 +162,6 @@ protected MongoClientSettings computeClientSetting() {
getOrDefault(port, "" + ServerAddress.defaultPort())));

Builder builder = MongoClientSettings.builder().applyConnectionString(connectionString);
builder.uuidRepresentation(UuidRepresentation.STANDARD);

if (mongoClientSettings != null) {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,14 @@
import java.net.URI;
import java.net.URL;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Currency;
import java.util.Date;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.atomic.AtomicInteger;
Expand Down Expand Up @@ -83,19 +88,65 @@ abstract class MongoConverters {
private MongoConverters() {}

/**
* Returns the converters to be registered.
* Returns the {@code Date} to UTC converters to be registered.
*
* @return
* @since 1.9
* @since 5.0
*/
static Collection<Object> getConvertersToRegister() {
static Collection<Object> getDateToUtcConverters() {

List<Object> converters = new ArrayList<>();
List<Object> converters = new ArrayList<>(3);

converters.add(DateToUtcLocalDateConverter.INSTANCE);
converters.add(DateToUtcLocalTimeConverter.INSTANCE);
converters.add(DateToUtcLocalDateTimeConverter.INSTANCE);

return converters;
}

/**
* Returns the {@code Decimal128} converters to be registered.
*
* @return
* @since 5.0
*/
static Collection<Object> getBigNumberDecimal128Converters() {

List<Object> converters = new ArrayList<>(3);

converters.add(BigDecimalToDecimal128Converter.INSTANCE);
converters.add(Decimal128ToBigDecimalConverter.INSTANCE);
converters.add(BigIntegerToDecimal128Converter.INSTANCE);

return converters;
}

/**
* Returns the {@code String} converters to be registered for {@link BigInteger} and {@link BigDecimal}.
*
* @return
* @since 5.0
*/
static Collection<Object> getBigNumberStringConverters() {

List<Object> converters = new ArrayList<>(4);

converters.add(BigDecimalToStringConverter.INSTANCE);
converters.add(BigIntegerToStringConverter.INSTANCE);

return converters;
}

/**
* Returns the converters to be registered.
*
* @return
* @since 1.9
*/
static Collection<Object> getConvertersToRegister() {

List<Object> converters = new ArrayList<>();

converters.add(URLToStringConverter.INSTANCE);
converters.add(StringToURLConverter.INSTANCE);
converters.add(DocumentToStringConverter.INSTANCE);
Expand All @@ -116,6 +167,9 @@ static Collection<Object> getConvertersToRegister() {
converters.add(ListToVectorConverter.INSTANCE);
converters.add(BinaryVectorToMongoVectorConverter.INSTANCE);

converters.add(StringToBigDecimalConverter.INSTANCE);
converters.add(StringToBigIntegerConverter.INSTANCE);

converters.add(reading(BsonUndefined.class, Object.class, it -> null));
converters.add(reading(String.class, URI.class, URI::create).andWriting(URI::toString));

Expand Down Expand Up @@ -630,4 +684,35 @@ public Instant convert(BsonTimestamp source) {
return Instant.ofEpochSecond(source.getTime(), 0);
}
}

@ReadingConverter
private enum DateToUtcLocalDateTimeConverter implements Converter<Date, LocalDateTime> {

INSTANCE;

@Override
public LocalDateTime convert(Date source) {
return LocalDateTime.ofInstant(Instant.ofEpochMilli(source.getTime()), ZoneId.of("UTC"));
}
}

@ReadingConverter
private enum DateToUtcLocalTimeConverter implements Converter<Date, LocalTime> {
INSTANCE;

@Override
public LocalTime convert(Date source) {
return DateToUtcLocalDateTimeConverter.INSTANCE.convert(source).toLocalTime();
}
}

@ReadingConverter
private enum DateToUtcLocalDateConverter implements Converter<Date, LocalDate> {
INSTANCE;

@Override
public LocalDate convert(Date source) {
return DateToUtcLocalDateTimeConverter.INSTANCE.convert(source).toLocalDate();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
*/
package org.springframework.data.mongodb.core.convert;

import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
Expand All @@ -32,6 +31,8 @@
import java.util.Set;
import java.util.function.Consumer;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jspecify.annotations.Nullable;
import org.springframework.core.convert.TypeDescriptor;
import org.springframework.core.convert.converter.Converter;
Expand All @@ -42,14 +43,9 @@
import org.springframework.data.convert.PropertyValueConverter;
import org.springframework.data.convert.PropertyValueConverterFactory;
import org.springframework.data.convert.PropertyValueConverterRegistrar;
import org.springframework.data.convert.ReadingConverter;
import org.springframework.data.convert.SimplePropertyValueConversions;
import org.springframework.data.convert.WritingConverter;
import org.springframework.data.mapping.model.SimpleTypeHolder;
import org.springframework.data.mongodb.core.convert.MongoConverters.BigDecimalToStringConverter;
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.mapping.MongoPersistentProperty;
import org.springframework.data.mongodb.core.mapping.MongoSimpleTypes;
import org.springframework.lang.Contract;
Expand All @@ -68,7 +64,7 @@
*/
public class MongoCustomConversions extends org.springframework.data.convert.CustomConversions {

private static final StoreConversions STORE_CONVERSIONS;
private static final Log LOGGER = LogFactory.getLog(MongoCustomConversions.class);
private static final List<Object> STORE_CONVERTERS;

static {
Expand All @@ -80,7 +76,6 @@ public class MongoCustomConversions extends org.springframework.data.convert.Cus
converters.addAll(GeoConverters.getConvertersToRegister());

STORE_CONVERTERS = Collections.unmodifiableList(converters);
STORE_CONVERSIONS = StoreConversions.of(MongoSimpleTypes.HOLDER, STORE_CONVERTERS);
}

/**
Expand Down Expand Up @@ -156,10 +151,11 @@ public static class MongoConverterConfigurationAdapter {
* 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 Set<Class<?>> JAVA_DRIVER_TIME_SIMPLE_TYPES = Set.of(LocalDate.class, LocalTime.class, LocalDateTime.class);
private static final Set<Class<?>> JAVA_DRIVER_TIME_SIMPLE_TYPES = Set.of(LocalDate.class, LocalTime.class,
LocalDateTime.class);

private boolean useNativeDriverJavaTimeCodecs = false;
private BigDecimalRepresentation bigDecimals = BigDecimalRepresentation.DECIMAL128;
private @Nullable BigDecimalRepresentation bigDecimals;
private final List<Object> customConverters = new ArrayList<>();

private final PropertyValueConversions internalValueConversion = PropertyValueConversions.simple(it -> {});
Expand Down Expand Up @@ -326,6 +322,7 @@ public MongoConverterConfigurationAdapter bigDecimal(BigDecimalRepresentation re
this.bigDecimals = representation;
return this;
}

/**
* Optionally set the {@link PropertyValueConversions} to be applied during mapping.
* <p>
Expand Down Expand Up @@ -375,72 +372,42 @@ ConverterConfiguration createConverterConfiguration() {
svc.init();
}

List<Object> converters = new ArrayList<>(STORE_CONVERTERS.size() + 7);

if (bigDecimals == BigDecimalRepresentation.STRING) {
List<Object> storeConverters = new ArrayList<>(STORE_CONVERTERS.size() + 10);

converters.add(BigDecimalToStringConverter.INSTANCE);
converters.add(StringToBigDecimalConverter.INSTANCE);
converters.add(BigIntegerToStringConverter.INSTANCE);
converters.add(StringToBigIntegerConverter.INSTANCE);
if (bigDecimals != null) {
switch (bigDecimals) {
case STRING -> storeConverters.addAll(MongoConverters.getBigNumberStringConverters());
case DECIMAL128 -> storeConverters.addAll(MongoConverters.getBigNumberDecimal128Converters());
}
} else if (LOGGER.isInfoEnabled()) {
LOGGER.info(
"No BigDecimal/BigInteger representation set. Choose [STRING] or [DECIMAL128] to store values in desired format.");
}

if (!useNativeDriverJavaTimeCodecs) {

converters.addAll(customConverters);
return new ConverterConfiguration(STORE_CONVERSIONS, converters, convertiblePair -> true,
this.propertyValueConversions);
}

/*
* We need to have those converters using UTC as the default ones would go on with the systemDefault.
*/
converters.add(DateToUtcLocalDateConverter.INSTANCE);
converters.add(DateToUtcLocalTimeConverter.INSTANCE);
converters.add(DateToUtcLocalDateTimeConverter.INSTANCE);
converters.addAll(STORE_CONVERTERS);

StoreConversions storeConversions = StoreConversions
.of(new SimpleTypeHolder(JAVA_DRIVER_TIME_SIMPLE_TYPES, MongoSimpleTypes.HOLDER), converters);

return new ConverterConfiguration(storeConversions, this.customConverters, convertiblePair -> {
if (useNativeDriverJavaTimeCodecs) {

// Avoid default registrations
/*
* We need to have those converters using UTC as the default ones would go on with the systemDefault.
*/
storeConverters.addAll(MongoConverters.getDateToUtcConverters());
storeConverters.addAll(STORE_CONVERTERS);

return !JAVA_DRIVER_TIME_SIMPLE_TYPES.contains(convertiblePair.getSourceType())
|| !Date.class.isAssignableFrom(convertiblePair.getTargetType());
}, this.propertyValueConversions);
}

@ReadingConverter
private enum DateToUtcLocalDateTimeConverter implements Converter<Date, LocalDateTime> {
StoreConversions storeConversions = StoreConversions
.of(new SimpleTypeHolder(JAVA_DRIVER_TIME_SIMPLE_TYPES, MongoSimpleTypes.HOLDER), storeConverters);

INSTANCE;
return new ConverterConfiguration(storeConversions, this.customConverters, convertiblePair -> {

@Override
public LocalDateTime convert(Date source) {
return LocalDateTime.ofInstant(Instant.ofEpochMilli(source.getTime()), ZoneId.of("UTC"));
}
}
// Avoid default registrations

@ReadingConverter
private enum DateToUtcLocalTimeConverter implements Converter<Date, LocalTime> {
INSTANCE;
return !JAVA_DRIVER_TIME_SIMPLE_TYPES.contains(convertiblePair.getSourceType())
|| !Date.class.isAssignableFrom(convertiblePair.getTargetType());
}, this.propertyValueConversions);

@Override
public LocalTime convert(Date source) {
return DateToUtcLocalDateTimeConverter.INSTANCE.convert(source).toLocalTime();
}
}

@ReadingConverter
private enum DateToUtcLocalDateConverter implements Converter<Date, LocalDate> {
INSTANCE;

@Override
public LocalDate convert(Date source) {
return DateToUtcLocalDateTimeConverter.INSTANCE.convert(source).toLocalDate();
}
storeConverters.addAll(STORE_CONVERTERS);
return new ConverterConfiguration(StoreConversions.of(MongoSimpleTypes.createSimpleTypeHolder(), storeConverters),
this.customConverters, convertiblePair -> true, this.propertyValueConversions);
}

private boolean hasDefaultPropertyValueConversions() {
Expand Down
Loading