Sau nhiều ngày nghiên cứu, tôi đã tìm ra giải pháp.
DutyBlockCodec phụ thuộc vào LocalDateCodec (mà tôi đã tạo) để mã hóa / giải mã. Sự phụ thuộc này không được thỏa mãn chỉ bằng cách thêm hai codec vào cùng một sổ đăng ký codec. Giải pháp là chuyển một CodecRegistry đối tượng chứa codec DutyBlockCodec phụ thuộc vào (ví dụ:một CodecRegistry chứa trong nó LocalDateCodec ) vào DutyBlockCodec hàm tạo của, được lưu trữ dưới dạng một biến thành viên. Để sử dụng LocalDateCodec để mã hóa, tôi sử dụng EncoderContext.encodeWithChildContext() phương thức, truyền codec, trình viết và phần tử để mã hóa. Ngoài ra, tôi viết các trường riêng lẻ thay vì viết một Document dưới dạng String (như trong mã gốc của tôi). Do đó, DutyBlock codec cuối cùng trông như thế này:
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 phụ thuộc vào codec khác và do đó yêu cầu CodecRegistry được chuyển vào hàm tạo của nó. Mặc dù tôi tin rằng có thể tạo CodecRegistry với LocalDateCodec , sau đó chuyển điều này làm đối số cho DutyBlockCodec hàm tạo của, sau đó tạo một CodecRegistry khác chứa cả LocalDateCodec và DutyBlockCodec , điều này khá khó hiểu và MongoDB cung cấp một chức năng, CodecProvider để tạo điều kiện thuận lợi cho quá trình này.
Sử dụng CodecProvider giao diện, tôi đã viết một 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;
}
}
Tôi đã thêm những CodecProviders này tới Ứng dụng khách MongoDB bằng CodecRegistries.fromProviders() phương pháp.
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");
Mã nguồn của tôi cho dự án này có thể được tìm thấy tại https://github.com/desrepair/DutySchedulerTôi sẵn sàng trả lời bất kỳ câu hỏi nào mà mọi người có thể có.