Reputation: 67
mongodb-driver-sync version 3.8.2
I'm trying to write a Class Parent
into the MongoDB database.
class Parent {
private Child child;
}
class Child {
private int a;
private String b;
}
I want to have custom codecs for both Classes and register them in a central location:
ConnectionString connString = new ConnectionString(connectionString);
MongoClientSettings settings = MongoClientSettings.builder()
.applyConnectionString(connString)
.codecRegistry(
CodecRegistries.fromRegistries(
MongoClientSettings.getDefaultCodecRegistry(),
CodecRegistries.fromCodecs(
////////////////////
//// HERE///////////
////////////////////
new ParentCodec(), new ChildCodec()
))
).build();
MongoClient client = MongoClients.create(settings);
........
However I'm unable to find out how to implement ParentCodec
correctly. Any examples I find are newing a DocumentCodec inside their custom Codec, which they then use to encode the document they generate, like so:
public class ParentCodec implements Codec<Parent> {
private Codec<Document> documentCodec = new DocumentCodec();
@Override
public void encode(BsonWriter bsonWriter,
Parent parent,
EncoderContext encoderContext)
{
Document doc = new Document();
doc.put("child", parent.getChild());
documentCodec.encode(bsonWriter, doc, encoderContext);
}
}
This fails, because the newed DocumentCodec only knows the codecs in the DefaultCodecRegistry:
org.bson.codecs.configuration.CodecConfigurationException: Can't find a codec for class package.Child.
at org.bson.codecs.configuration.CodecCache.getOrThrow(CodecCache.java:46)
at org.bson.codecs.configuration.ProvidersCodecRegistry.get(ProvidersCodecRegistry.java:63)
at org.bson.codecs.configuration.ProvidersCodecRegistry.get(ProvidersCodecRegistry.java:37)
at org.bson.codecs.DocumentCodec.writeValue(DocumentCodec.java:184)
at org.bson.codecs.DocumentCodec.writeIterable(DocumentCodec.java:207)
at org.bson.codecs.DocumentCodec.writeValue(DocumentCodec.java:180)
at org.bson.codecs.DocumentCodec.writeMap(DocumentCodec.java:199)
at org.bson.codecs.DocumentCodec.encode(DocumentCodec.java:141)
at org.bson.codecs.DocumentCodec.encode(DocumentCodec.java:45)
Is there any way around this? I mean, I could obviously do something like this:
public class ParentCodec implements Codec<Parent> {
private Codec<Document> documentCodec = new DocumentCodec(
CodecRegistries.fromRegistries(
MongoClientSettings.getDefaultCodecRegistry(),
CodecRegistries.fromCodecs(
new ChildCodec()
)));
But this is ugly and I lose out on being able to register all my codecs in one central location. Anything else, that I missed?
Upvotes: 2
Views: 3089
Reputation: 2520
Pass the CodecRegistry to your codecs. Then in the codecs, get the DocumentCodec from the registry (using registry.get(Document.class)
) instead of calling new
.
The DocumentCodec will then be aware of all of the other Codecs in the registry.
public class ParentCodec implements Codec<Parent> {
private final CodecRegistry registry;
private final Codec<Document> documentCodec;
/**
* Registry constructor.
*
* @param registry The CodecRegistry to use.
*/
public ParentCodec(CodecRegistry registry) {
this.registry = registry;
this.documentCodec = this.registry.get(Document.class);
}
// ...
}
public class Main {
public static void main(String[] args) {
// ...
CodecRegistry codecRegistry = MongoClient.getDefaultCodecRegistry();
codecRegistry = CodecRegistries.fromRegistries(
CodecRegistries.fromCodecs(new ParentCodec(codecRegistry), new ChildCodec(codecRegistry)),
codecRegistry
);
// ...
}
}
Upvotes: 1