Setelah beberapa hari melakukan penelitian, saya menemukan solusinya.
DutyBlockCodec tergantung pada LocalDateCodec (yang saya buat) untuk menyandikan/mendekode. Ketergantungan ini tidak terpenuhi hanya dengan menambahkan dua codec ke dalam registri codec yang sama. Solusinya adalah dengan memberikan CodecRegistry objek yang berisi codec yang DutyBlockCodec tergantung pada (mis. CodecRegistry berisi LocalDateCodec di dalamnya ) ke DutyBlockCodec 's konstruktor, yang disimpan sebagai variabel anggota. Untuk menggunakan LocalDateCodec untuk encode, saya menggunakan EncoderContext.encodeWithChildContext() metode, meneruskan codec, penulis, dan elemen untuk dikodekan. Selain itu, saya menulis bidang individual daripada menulis Document sebagai String (seperti dalam kode asli saya). Jadi DutyBlock codec akhirnya terlihat seperti ini:
public class DutyBlockCodec implements Codec<DutyBlock> {
private final CodecRegistry codecRegistry;
public DutyBlockCodec(final CodecRegistry codecRegistry) {
this.codecRegistry = codecRegistry;
}
@Override
public void encode(BsonWriter writer, DutyBlock t, EncoderContext ec) {
writer.writeStartDocument();
Codec dateCodec = codecRegistry.get(LocalDate.class);
writer.writeName("startDate");
ec.encodeWithChildContext(dateCodec, writer, t.getStartDate());
writer.writeName("endDate");
ec.encodeWithChildContext(dateCodec, writer, t.getEndDate());
writer.writeName("blockLength");
writer.writeInt32(t.getBlockLength());
writer.writeName("pointValue");
writer.writeDouble(t.getPointValue());
//Writing ArrayList of RAs
writer.writeName("assigned");
writer.writeStartArray();
for (Ra ra : t.getRasOnDuty()) {
Codec raCodec = codecRegistry.get(Ra.class);
ec.encodeWithChildContext(raCodec, writer, ra);
}
writer.writeEndArray();
writer.writeEndDocument();
}
@Override
public Class<DutyBlock> getEncoderClass() {
return DutyBlock.class;
}
@Override
public DutyBlock decode(BsonReader reader, DecoderContext dc) {
reader.readStartDocument();
Codec<LocalDate> dateCodec = codecRegistry.get(LocalDate.class);
reader.readName();
LocalDate startDate = dateCodec.decode(reader, dc);
reader.readName();
LocalDate endDate = dateCodec.decode(reader, dc);
reader.readName();
int blockLength = reader.readInt32();
reader.readName();
double pointValue = reader.readDouble();
//Reading ArrayList of RAs
reader.readName();
Codec<Ra> raCodec = codecRegistry.get(Ra.class);
ArrayList<Ra> rasOnDuty = new ArrayList<>();
reader.readStartArray();
while (reader.readBsonType() != BsonType.END_OF_DOCUMENT) {
rasOnDuty.add(raCodec.decode(reader, dc));
}
reader.readEndArray();
reader.readEndDocument();
return new DutyBlock(startDate, endDate, blockLength, pointValue, rasOnDuty);
}
}
DutyBlockCodec bergantung pada codec lain, sehingga memerlukan CodecRegistry untuk diteruskan ke konstruktornya. Meskipun saya yakin itu mungkin untuk membuat CodecRegistry dengan LocalDateCodec , lalu berikan ini sebagai argumen ke DutyBlockCodec konstruktor , lalu buat CodecRegistry lainnya berisi LocalDateCodec dan DutyBlockCodec , ini agak membingungkan, dan MongoDB menyediakan fungsionalitas, CodecProvider untuk memfasilitasi proses ini.
Menggunakan CodecProvider antarmuka, saya menulis DutyBlockCodecProvider
public class DutyBlockCodecProvider implements CodecProvider {
@Override
public <T> Codec<T> get(Class<T> type, CodecRegistry cr) {
if (type == DutyBlock.class) {
return (Codec<T>) new DutyBlockCodec(cr);
}
return null;
}
}
Saya menambahkan CodecProviders ini ke Klien MongoDB menggunakan CodecRegistries.fromProviders() metode.
CodecRegistry codecRegistry = CodecRegistries.fromRegistries(
CodecRegistries.fromCodecs(new LocalDateCodec()),
CodecRegistries.fromProviders(
new RaCodecProvider(),
new DutyBlockCodecProvider(),
new ScheduledDutyCodecProvider()),
MongoClient.getDefaultCodecRegistry());
MongoClientOptions options = MongoClientOptions.builder()
.codecRegistry(codecRegistry).build();
mongoClient = new MongoClient(new ServerAddress(), options);
db = mongoClient.getDatabase("DutySchedulerDB");
Kode sumber saya untuk proyek ini dapat ditemukan di https://github.com/desrepair/DutySchedulerSaya terbuka untuk menjawab pertanyaan apa pun yang mungkin dimiliki orang.