From ae81d87fba97c2aa71900da2c1e075f9e484bdc4 Mon Sep 17 00:00:00 2001 From: Denis Stepanov Date: Mon, 16 Sep 2024 11:04:31 +0200 Subject: [PATCH] MongoDB: Ignore basic types codecs --- .../mongodb/serde/DataDecoderContext.java | 15 ++-- .../mongodb/serde/DataEncoderContext.java | 12 +++- .../document/mongodb/MongoRuntimeSpec.groovy | 71 +++++++++++++++++++ 3 files changed, 89 insertions(+), 9 deletions(-) create mode 100644 data-mongodb/src/test/groovy/io/micronaut/data/document/mongodb/MongoRuntimeSpec.groovy diff --git a/data-mongodb/src/main/java/io/micronaut/data/mongodb/serde/DataDecoderContext.java b/data-mongodb/src/main/java/io/micronaut/data/mongodb/serde/DataDecoderContext.java index 76f9b98111..388ee55770 100644 --- a/data-mongodb/src/main/java/io/micronaut/data/mongodb/serde/DataDecoderContext.java +++ b/data-mongodb/src/main/java/io/micronaut/data/mongodb/serde/DataDecoderContext.java @@ -18,6 +18,7 @@ import io.micronaut.core.annotation.Internal; import io.micronaut.core.beans.BeanIntrospection; import io.micronaut.core.convert.ConversionContext; +import io.micronaut.core.reflect.ClassUtils; import io.micronaut.core.type.Argument; import io.micronaut.data.annotation.GeneratedValue; import io.micronaut.data.annotation.MappedProperty; @@ -39,7 +40,6 @@ import org.bson.BsonDocument; import org.bson.codecs.BsonDocumentCodec; import org.bson.codecs.Codec; -import org.bson.codecs.IterableCodec; import org.bson.codecs.configuration.CodecRegistry; import org.bson.types.ObjectId; @@ -180,11 +180,14 @@ public Deserializer findDeserializer(Argument type if (codec instanceof MappedCodec mappedCodec) { return mappedCodec.deserializer; } - if (codec != null - && !(codec instanceof IterableCodec) - && !(Map.class.isAssignableFrom(codec.getEncoderClass())) - && !(Collection.class.isAssignableFrom(codec.getEncoderClass()))) { - return new CodecBsonDecoder<>((Codec) codec); + if (codec != null) { + // Eliminate codecs for basic types and collections + Class encoderClass = codec.getEncoderClass(); + if (!ClassUtils.isJavaLangType(encoderClass) + && !Map.class.isAssignableFrom(encoderClass) + && !Iterable.class.isAssignableFrom(encoderClass)) { + return new CodecBsonDecoder<>((Codec) codec); + } } return parent.findDeserializer(type); } diff --git a/data-mongodb/src/main/java/io/micronaut/data/mongodb/serde/DataEncoderContext.java b/data-mongodb/src/main/java/io/micronaut/data/mongodb/serde/DataEncoderContext.java index b77d934b4d..359f7828c4 100644 --- a/data-mongodb/src/main/java/io/micronaut/data/mongodb/serde/DataEncoderContext.java +++ b/data-mongodb/src/main/java/io/micronaut/data/mongodb/serde/DataEncoderContext.java @@ -18,6 +18,7 @@ import io.micronaut.core.annotation.Internal; import io.micronaut.core.convert.ConversionContext; import io.micronaut.core.convert.ConversionService; +import io.micronaut.core.reflect.ClassUtils; import io.micronaut.core.type.Argument; import io.micronaut.data.annotation.GeneratedValue; import io.micronaut.data.annotation.MappedProperty; @@ -35,7 +36,6 @@ import io.micronaut.serde.reference.PropertyReference; import io.micronaut.serde.reference.SerializationReference; import org.bson.codecs.Codec; -import org.bson.codecs.IterableCodec; import org.bson.codecs.configuration.CodecRegistry; import org.bson.types.ObjectId; @@ -164,8 +164,14 @@ public Serializer findSerializer(Argument type) thro if (codec instanceof MappedCodec mappedCodec) { return mappedCodec.serializer; } - if (codec != null && !(codec instanceof IterableCodec) && !(Map.class.isAssignableFrom(codec.getEncoderClass()))) { - return new CodecBsonDecoder<>((Codec) codec); + if (codec != null) { + // Eliminate codecs for basic types and collections + Class encoderClass = codec.getEncoderClass(); + if (!ClassUtils.isJavaLangType(encoderClass) + && !Map.class.isAssignableFrom(encoderClass) + && !Iterable.class.isAssignableFrom(encoderClass)) { + return new CodecBsonDecoder<>((Codec) codec); + } } return parent.findSerializer(type); } diff --git a/data-mongodb/src/test/groovy/io/micronaut/data/document/mongodb/MongoRuntimeSpec.groovy b/data-mongodb/src/test/groovy/io/micronaut/data/document/mongodb/MongoRuntimeSpec.groovy new file mode 100644 index 0000000000..b4cd1d881e --- /dev/null +++ b/data-mongodb/src/test/groovy/io/micronaut/data/document/mongodb/MongoRuntimeSpec.groovy @@ -0,0 +1,71 @@ +package io.micronaut.data.document.mongodb + +import groovy.transform.CompileStatic +import io.micronaut.context.ApplicationContext +import io.micronaut.core.annotation.Introspected +import io.micronaut.data.annotation.MappedEntity +import io.micronaut.data.mongodb.annotation.MongoRepository +import io.micronaut.data.repository.CrudRepository +import io.micronaut.serde.annotation.Serdeable +import io.micronaut.test.extensions.spock.annotation.MicronautTest +import jakarta.inject.Inject +import jakarta.persistence.Id +import spock.lang.AutoCleanup +import spock.lang.Shared +import spock.lang.Specification + +@MicronautTest +class MongoRuntimeSpec extends Specification implements MongoTestPropertyProvider { + @AutoCleanup + @Shared + ApplicationContext applicationContext = ApplicationContext.run(getProperties()) + + @Shared + @Inject + TestContentRepository contentRepository = applicationContext.getBean(TestContentRepository) + + def cleanup() { + contentRepository.deleteAll() + } + + void 'test runtime serialization'() { + given: + TestContent testContent = new TestContent( + id: 'test', + category: [ + one : 'one', + two : 2, + three: false + ] + ) + + when: + contentRepository.save(testContent) + then: + contentRepository.findById('test').get().category == testContent.category + } + +} + +@CompileStatic +@MongoRepository +interface TestContentRepository extends CrudRepository { +} + +@CompileStatic +@Serdeable +@MappedEntity +@Introspected +class TestContent { + + @Id + String id + + BigDecimal number + + + String propertyId = null // Property name. + + + Map category = null +}