-
Type:
Task
-
Resolution: Works as Designed
-
Priority:
Major - P3
-
None
-
Affects Version/s: 3.6.3
-
Component/s: Codecs
-
None
-
Environment:Spring Boot 2.0.1.RELEASE
-
None
-
None
-
None
-
None
-
None
-
None
-
None
Context
I followed the insructions in mongo.github (related to JAVA-1741) to serialise a field of type OffsetDateTime to Bson String.
Neither the codec not the codecProvider are used during the write operations. The field is then stored in the database as Object:
updatedOn Object: dateTime "2018-04-16 17:11:09.315Z" Date offset "+01:00" String
On read operations, the codec is invoked for dateTime and offset fields to deserialise them to an object of type OffsetDateTime. Of course it fails because the codec does not know how to process the offset field.
I have not tested this in Spring Boot 1.x as of yet.
Can't really tell whether this is a configuration problem or a bug. Hence the question "what may be wrong here" instead of a suggestion.
Implementation and configuration details
MongoConfig extends AbstractMongoConfiguration
@Override public MongoClient mongoClient() { CodecRegistry defaultCodecRegistry = MongoClient.getDefaultCodecRegistry(); Map<BsonType, Class<?>> replacements = new HashMap<BsonType, Class<?>>(); replacements.put(BsonType.DATE_TIME, OffsetDateTime.class); BsonTypeClassMap bsonTypeClassMap = new BsonTypeClassMap(replacements); DocumentCodecProvider documentCodecProvider = new DocumentCodecProvider(bsonTypeClassMap); Codec<OffsetDateTime> offsetDateTimeCodec = new OffsetDateTimeCodec(); CodecRegistry codecRegistry = CodecRegistries. fromRegistries(CodecRegistries.fromCodecs(offsetDateTimeCodec), CodecRegistries.fromProviders(documentCodecProvider), defaultCodecRegistry); MongoClientOptions mcs = MongoClientOptions.builder() .codecRegistry(codecRegistry) .build(); return new MongoClient(new ServerAddress(), mcs); }
DocumentCodecProvider.java
public class DocumentCodecProvider implements CodecProvider { private final BsonTypeClassMap bsonTypeClassMap; public DocumentCodecProvider(final BsonTypeClassMap bsonTypeClassMap) { this.bsonTypeClassMap = bsonTypeClassMap; } @Override public <T> Codec<T> get(final Class<T> clazz, final CodecRegistry registry) { if (clazz == Document.class) { // construct DocumentCodec with a CodecRegistry and a BsonTypeClassMap return (Codec<T>) new DocumentCodec(registry, bsonTypeClassMap); } return null; } }
OffsetDateTimeCodec.java
public class OffsetDateTimeCodec implements Codec<OffsetDateTime> { @Override public void encode(final BsonWriter writer, final OffsetDateTime value, final EncoderContext encoderContext) { writer.writeString(value.toString()); } @Override public OffsetDateTime decode(final BsonReader reader, final DecoderContext decoderContext) { return OffsetDateTime.parse(reader.readString()); } @Override public Class<OffsetDateTime> getEncoderClass() { return OffsetDateTime.class; } }
DocRepository.java
public interface DocRepository extends MongoRepository<DocEntity, String> { public List<DocEntity> findAll(); public SchemaDocumentEntity insert(DocEntity formSchemaDocumentEntity); }
DocEntity.java
@Document public class DocEntity { @Id private ObjectId documentId; private OffsetDateTime updatedOn; }