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.