Add a property for Data MongoDB's BigDecimal representation

Closes gh-47041
This commit is contained in:
Andy Wilkinson
2025-09-05 15:07:52 +01:00
parent 1554c74c2a
commit a977d260bd
4 changed files with 70 additions and 7 deletions
@@ -19,6 +19,7 @@ package org.springframework.boot.data.mongodb.autoconfigure;
import org.jspecify.annotations.Nullable;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.data.mongodb.core.convert.MongoCustomConversions.BigDecimalRepresentation;
/**
* Configuration properties for Spring Data MongoDB.
@@ -41,6 +42,8 @@ public class DataMongoProperties {
private final Gridfs gridfs = new Gridfs();
private final Representation representation = new Representation();
public @Nullable Boolean isAutoIndexCreation() {
return this.autoIndexCreation;
}
@@ -61,6 +64,10 @@ public class DataMongoProperties {
return this.gridfs;
}
public Representation getRepresentation() {
return this.representation;
}
public static class Gridfs {
/**
@@ -91,4 +98,21 @@ public class DataMongoProperties {
}
public static class Representation {
/**
* Representation to use when converting a BigDecimal.
*/
private BigDecimalRepresentation bigDecimal = BigDecimalRepresentation.DECIMAL128;
public BigDecimalRepresentation getBigDecimal() {
return this.bigDecimal;
}
public void setBigDecimal(BigDecimalRepresentation bigDecimal) {
this.bigDecimal = bigDecimal;
}
}
}
@@ -16,8 +16,6 @@
package org.springframework.boot.data.mongodb.autoconfigure;
import java.util.Collections;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
@@ -48,6 +46,12 @@ import org.springframework.data.mongodb.core.mapping.MongoMappingContext;
@Configuration(proxyBeanMethods = false)
class MongoDataConfiguration {
private final DataMongoProperties properties;
MongoDataConfiguration(DataMongoProperties properties) {
this.properties = properties;
}
@Bean
@ConditionalOnMissingBean
static MongoManagedTypes mongoManagedTypes(ApplicationContext applicationContext) throws ClassNotFoundException {
@@ -56,13 +60,12 @@ class MongoDataConfiguration {
@Bean
@ConditionalOnMissingBean
MongoMappingContext mongoMappingContext(DataMongoProperties properties, MongoCustomConversions conversions,
MongoManagedTypes managedTypes) {
MongoMappingContext mongoMappingContext(MongoCustomConversions conversions, MongoManagedTypes managedTypes) {
PropertyMapper map = PropertyMapper.get().alwaysApplyingWhenNonNull();
MongoMappingContext context = new MongoMappingContext();
map.from(properties.isAutoIndexCreation()).to(context::setAutoIndexCreation);
map.from(this.properties.isAutoIndexCreation()).to(context::setAutoIndexCreation);
context.setManagedTypes(managedTypes);
Class<?> strategyClass = properties.getFieldNamingStrategy();
Class<?> strategyClass = this.properties.getFieldNamingStrategy();
if (strategyClass != null) {
context.setFieldNamingStrategy((FieldNamingStrategy) BeanUtils.instantiateClass(strategyClass));
}
@@ -73,7 +76,8 @@ class MongoDataConfiguration {
@Bean
@ConditionalOnMissingBean
MongoCustomConversions mongoCustomConversions() {
return new MongoCustomConversions(Collections.emptyList());
return MongoCustomConversions
.create((configurer) -> configurer.bigDecimal(this.properties.getRepresentation().getBigDecimal()));
}
@Bean
@@ -20,6 +20,9 @@ import org.junit.jupiter.api.Test;
import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import org.springframework.data.mongodb.core.convert.MongoCustomConversions.BigDecimalRepresentation;
import org.springframework.data.mongodb.core.convert.MongoCustomConversions.MongoConverterConfigurationAdapter;
import org.springframework.test.util.ReflectionTestUtils;
import static org.assertj.core.api.Assertions.assertThat;
@@ -40,4 +43,16 @@ class DataMongoPropertiesTests {
});
}
@Test
void defaultBigDecimalRepresentationIsAlignedWithSpringData() {
BigDecimalRepresentation springDataDefault = springDataDefaultBigDecimalRepresentation();
BigDecimalRepresentation springBootDefault = new DataMongoProperties().getRepresentation().getBigDecimal();
assertThat(springBootDefault).isEqualTo(springDataDefault);
}
private BigDecimalRepresentation springDataDefaultBigDecimalRepresentation() {
return (BigDecimalRepresentation) ReflectionTestUtils.getField(new MongoConverterConfigurationAdapter(),
"bigDecimals");
}
}
@@ -118,6 +118,26 @@ class MongoDataAutoConfigurationTests {
});
}
@Test
void customBigDecimalRepresentation() {
this.contextRunner.withPropertyValues("spring.data.mongodb.representation.big-decimal=string")
.run((context) -> assertThat(context.getBean(MongoCustomConversions.class)).extracting("converters")
.asInstanceOf(InstanceOfAssertFactories.LIST)
.map((converter) -> converter.getClass().getName())
.anySatisfy((className) -> assertThat(className).contains("BigDecimalToStringConverter"))
.anySatisfy((className) -> assertThat(className).contains("BigIntegerToStringConverter")));
}
@Test
void defaultBigDecimalRepresentation() {
this.contextRunner
.run((context) -> assertThat(context.getBean(MongoCustomConversions.class)).extracting("converters")
.asInstanceOf(InstanceOfAssertFactories.LIST)
.map((converter) -> converter.getClass().getName())
.noneSatisfy((className) -> assertThat(className).contains("BigDecimalToStringConverter"))
.noneSatisfy((className) -> assertThat(className).contains("BigIntegerToStringConverter")));
}
@Test
void usesAutoConfigurationPackageToPickUpDocumentTypes() {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();