Hello world,
I have a problem converting my Java Record data structure to an appropriate BSON representation to save it to the data base.
Be patient with me…
I have this interface:
* Java 21 syntax.
public sealed interface Car permits Lambo, Ferr, Paga, Lotu {
String lPlate;
}
And those Records:
public record Lambo(String lPlate, Integer color) implements Car { }
public record Ferr(String lPlate, Integer maxSpeed) implements Car { }
public record Paga(String lPlate, Integer year) implements Car { }
public record Lotu(String lPlate, Integer size) implements Car { }
Now i have this Record:
public record Parking(Integer size, Car...) { }
When i try to insertOne(parking) it throws:
org.bson.codecs.configuration.CodecConfigurationException: Can’t find a codec for CodecCacheKey{clazz=class [Lmy.example.Car;, types=null}.
If you notice the class name starts with “[L” my.example.Car after some research i found that it’s because BSON having a problem to handle java arbitrary syntax “…” for Car
To overcome this i implemented CarCodecProvider:
public class CarCodecProvider implements CodecProvider {
@Override
@SuppressWarnings("unchecked")
public <T> Codec<T> get(Class<T> aClass, CodecRegistry codecRegistry) {
if (aClass == Car[].class) {
return (Codec<T>) new CarCodec(codecRegistry);
}
return null;
}
}
I had a progress but,
Now the question is how to implement “CarCodec”?
I achieved this but i stuck, see comments
public class CarCodec implements Codec<Car[]> {
private final CodecRegistry registry;
public RuleCodec(CodecRegistry registry) {
this.registry = registry;
}
@Override
public void encode(BsonWriter writer, Car[] cars, EncoderContext encoderContext) {
writer.writeStartArray();
for (Car car : cars) {
// This part works because it using RecordCodec
// meaning "codec" type is RecordCodec
// but obviously it doesn't containing the data type: "Lambo, Ferr, Paga, Lotu"
Codec codec = registry.get(car.getClass());
encoderContext.encodeWithChildContext(codec, writer, car);
}
writer.writeEndArray();
}
@Override
public Car[] decode(BsonReader reader, DecoderContext decoderContext) {
List<Car> cars = new ArrayList<>();
reader.readStartArray();
while (reader.readBsonType().isContainer()) {
// This part doesn't work!
Codec codec = registry.get(Car.class);
cars.add((Car) decoderContext.decodeWithChildContext(codec, reader));
}
reader.readEndArray();
return cars.toArray(new Cars[0]);
}
@Override
public Class<Car[]> getEncoderClass() {
return Car[].class;
}
Thank you for your patience and help.
PS: BSON RecordCodec doesn’t support the annotation “BsonDiscriminator”