简体   繁体   中英

Can't find a codec for my class (CodecConfigurationException)

I need to save a java object in mongodb database. This object has an other object into it. When I try to save, I receive the error message on console:

org.bson.codecs.configuration.CodecConfigurationException: Can't find a codec for class Item.

The problem is that I created the codec for class Item, but, it can't work even registering it. See the classes for best understanding.

Models

public class Card(){

  public Card(){
   itens = new ArrayList<Item>()
  }
  String id;
  String description;
  List<Item> itens;
  .
  .
  .

}
public class Item(){

  String id;
  String name; 
  .
  .
  .

}

CardCodec

public class CardCodec implements CollectibleCodec<Card>{
  private final Codec<Document> documentCodec;

  public CardCodec() {      
    this.documentCodec = new DocumentCodec();
  }

  @Override
  public void encode(BsonWriter writer, Card card, EncoderContext encoderContext) {
  Document cardDoc = new Document();
    String id = card.getId();
    String description = card.getDescription();  
    List<Item> itens = card.getItens();

    if(id != null) {
        cardDoc.put("_id", new ObjectId(id));
    }
    if(description != null){
        cardDoc.put("description", card.getDescription);
    }
    if(Itens != null){
        cardDoc.put("itens", card.getItens());
    }
    this.documentCodec.encode(writer, cardDoc, encoderContext);
  }

    @Override
    public Class<Card> getEncoderClass() {      
        return Card.class;
    }

    @Override
    public Card decode(BsonReader reader, DecoderContext decoderContext) {
        Document cardDoc = this.documentCodec.decode(reader, decoderContext);
        Card card=  new Card();

        card.setId(cardDoc .getObjectId("_id").toHexString());
        card.setDescription(cardDoc .getString("description"));

        List<Document> itensDoc =  cardDoc.getList("itens", Document.class);
        List<Item> itens = new ItemConverter().convertToListItem(itensDoc);
        card.setItens(itens);
        return card;
    }

    @Override
    public Card generateIdIfAbsentFromDocument(Card card) {

        if( !documentHasId(card) ) {
        card.setId(new ObjectId().toHexString());
        }

        return card;

    }

    @Override
    public boolean documentHasId(Card card) {       
        return null != card.getId();
    }

    @Override
    public BsonValue getDocumentId(Card card) {
        if(!documentHasId(card)) {
            throw new IllegalStateException("Esse documento não tem um _id");
        }
        return new BsonString(card.getId());
    }

}

Converter

public class ItemConverter {

    public Item convert(Document doc) {
        Item item = new Item();
        String id = doc.getObjectId("_id").toHexString();
        String description = doc.getString("description");
        item.setId(id);
        item.setName(description);
        return item;
    }

    public List<Item> convertToListItem(List<Document> ItensDocs){      
        List<Item> itens = new ArrayList<Item>();   
        if(ItensDocs== null) {
           return Collections.emptyList();
        }
        for(Document doc: ItensDocs) {           
           itens.add( this.convert(doc) );
        }
        return itens;
    }

}

ItemCodec

public class ItemCodec implements CollectibleCodec<Item>{
    private final Codec<Document> documentCodec;

    public ItemCodec() {    
        this.documentCodec = new DocumentCodec();
    }

    @Override
    public void encode(BsonWriter writer, Item value, EncoderContext encoderContext) {
        Document itemDoc = new Document();

        String id = value.getId();
        String name = value.getName();

        if(id != null) {
            itemDoc.put("_id", new ObjectId(id));
        }
        if(name != null) {
            itemDoc.put("name", value.getName());
        }

        documentCodec.encode(writer, itemDoc, encoderContext);
    }

    @Override
    public Class<Item> getEncoderClass() {      
        return Item.class;
    }

    @Override
    public Item decode(BsonReader reader, DecoderContext decoderContext) {      
        Document document = documentCodec.decode(reader, decoderContext);       
        return new ItemConverter().convert(document);
    }

    @Override
    public Item generateIdIfAbsentFromDocument(Item item) {
        if(!this.documentHasId(item)) {
            item.setId(new ObjectId().toHexString());           
        }
        return item;        
    }

    @Override
    public boolean documentHasId(Item item) {       
        return null != item.getId();
    }

    @Override
    public BsonValue getDocumentId(Item item) {
        if(!documentHasId(item)) {
            throw new IllegalStateException("Esse documento não tem um _id");
        }

        return new BsonString(item.getId());

    }


}

Now, how I registry the codecs

...
    CardCodec cardCodec = new CardCodec();
    ItemCodec itemCodec = new ItemCodec();

    this.codecRegistry = CodecRegistries.fromRegistries(
                MongoClientSettings.getDefaultCodecRegistry(),
                CodecRegistries.fromCodecs(cardCodec, itemCodec)
    );

this.cardCollection = this.mongoDatabase.getCollection("cards", Card.class).withCodecRegistry(this.codecRegistry);
...

When I try to execute an insert:

this.cardCollection.insertOne(card);

I receive:

org.bson.codecs.configuration.CodecConfigurationException

It's tricky to write correct and efficient POJO Codec implementations by hand. In this case the problem is that the DocumentCodec that you instantiate within the CardCodec is not configured with a CodecRegistry that contains the ItemCodec, so it is unable to find the ItemCodec.

There are ways that you can fix your Codec implementations, but I'm not clear why you want to roll your own when the driver has a general solution for this. See POJO Support for details.

Simply create your CodecRegistry like this:

        CodecRegistry codecRegistry = CodecRegistries.fromRegistries(
            MongoClientSettings.getDefaultCodecRegistry(),
            CodecRegistries.fromProviders(PojoCodecProvider.builder().automatic(true).build())
    );

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM