Can't find a codec for my class

Darshan Puranik picture Darshan Puranik · Nov 2, 2017 · Viewed 17.6k times · Source

I have simple class named Signal. Class looks as follows:

public class Signal {
    private String id;
    private Date timestamp;

    public String getId() {
        return id;
    }
    public void setId(String id) {
        this.id = id;
    }
    public Date getTimestamp() {
        return timestamp;
    }
    public void setTimestamp(Date timestamp) {
        this.timestamp = timestamp;
    }
}

I am trying to insert signal in MongoDB (v3.4). I am using the following method to insert:

public boolean xyz(Signal signal) {
            try {
                DatabaseConnection databaseConnection =DatabaseConnection.getInstance();
                MongoClient mongoClient = databaseConnection.getMongoClient();
                MongoDatabase db = mongoClient.getDatabase("myDb"); 
                MongoCollection<Signal> collection = db.getCollection("myCollection", Signal.class);
                collection.insertOne(signal);

                return true;
            } catch (Exception e){
                logger.error("Error", e);
                return false;
            }

        }

I am getting the following exception:

org.bson.codecs.configuration.CodecConfigurationException: Can't find a codec for class in.co.mysite.webapi.models.Signal.

I checked a similar question here but insertion code is different. I took the hint from answer and modified my method but it doesn't look clean. Modified method is as follows:

public boolean xyz(Signal signal) {
        try {
            DatabaseConnection databaseConnection =DatabaseConnection.getInstance();
            MongoClient mongoClient = databaseConnection.getMongoClient();
            MongoDatabase db = mongoClient.getDatabase("myDb"); 
            MongoCollection<Document> collection = db.getCollection("myCollection");

            Document doc = new Document();

            doc.put("id", signal.getId());
            doc.put("timestamp", signal.getTimestamp());
            doc.put("_id", new ObjectId().toString());

            collection.insertOne(doc);

            return true;
        } catch (Exception e){
            logger.error("Error", e);
            return false;
        }

    }

Answer

M3HD1 picture M3HD1 · Aug 15, 2018

You need to configure a CodecRegistry which will manage the translation from bson to your pojos:

MongoClientURI connectionString = new MongoClientURI("mongodb://localhost:27017");
        MongoClient mongoClient = new MongoClient(connectionString);
        CodecRegistry pojoCodecRegistry = org.bson.codecs.configuration.CodecRegistries.fromRegistries(MongoClientSettings.getDefaultCodecRegistry(), org.bson.codecs.configuration.CodecRegistries.fromProviders(PojoCodecProvider.builder().automatic(true).build()));
        MongoDatabase database = mongoClient.getDatabase("testdb").withCodecRegistry(pojoCodecRegistry);  

PS: You could statically import org.bson.codecs.configuration.CodecRegistries.fromRegistries and org.bson.codecs.configuration.CodecRegistries.fromProviders.

A full example could be found in github.
The Mongodb java driver documentation contains also an article about managing pojos (The link is for the 3.8.0 driver version).