Après plusieurs jours de recherche, j'ai trouvé une solution.
Le DutyBlockCodec
dépend du LocalDateCodec
(que j'ai créé) afin d'encoder/décoder. Cette dépendance n'est pas satisfaite simplement en ajoutant les deux codecs dans le même registre de codecs. La solution est de passer un CodecRegistry
objet contenant les codecs que DutyBlockCodec
dépend de (par exemple, un CodecRegistry
contenant en son sein le LocalDateCodec
) au DutyBlockCodec
le constructeur de , qui est stocké en tant que variable membre. Pour utiliser le LocalDateCodec
pour encoder, j'utilise le EncoderContext.encodeWithChildContext()
méthode, en transmettant le codec, le rédacteur et l'élément à encoder. De plus, j'écris des champs individuels plutôt que d'écrire un Document
sous forme de String
(comme dans mon code d'origine). Ainsi le DutyBlock
codec finit par ressembler à ceci :
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
dépend d'un autre codec, et nécessite donc un CodecRegistry
à transmettre à son constructeur. Bien que je pense qu'il est possible de créer un CodecRegistry
avec le LocalDateCodec
, puis passez ceci comme argument à DutyBlockCodec
du constructeur, puis créez un autre CodecRegistry
contenant à la fois LocalDateCodec
et DutyBlockCodec
, c'est plutôt déroutant, et MongoDB fournit une fonctionnalité, le CodecProvider
pour faciliter ce processus.
Utilisation du CodecProvider
interface, j'ai écrit un 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;
}
}
J'ai ajouté ces CodecProviders
au client MongoDB en utilisant le CodecRegistries.fromProviders()
méthode.
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");
Mon code source pour ce projet peut être trouvé à https://github.com/desrepair/DutySchedulerJe suis ouvert à répondre à toutes les questions que les gens pourraient avoir.