31

I'm learning MongoDB with Java. I'm trying to insert data to MongoDB with Java driver. I'm doing inserting like in MongoDB tutorial and every thing is okey. But if I want to insert a variable and when I run the code, driver throws an error like this:

org.bson.codecs.configuration.CodecConfigurationException: Can't find a codec for class io.github.ilkgunel.mongodb.Pojo.

I searhed questions in Stack Overflow like this but I couldn't understand anything and I cant't find anything to solve this error. My code is below. How can solve this problem?

I'm using this code:

package io.github.ilkgunel.mongodb;
import org.bson.Document;

import com.mongodb.MongoClient;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoDatabase;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Locale;

public class MongoDBBasicUsage {
    public static void main(String[] args) {
        MongoClient mongoClient;
        try {
            Pojo pojo = new Pojo();
            mongoClient = new MongoClient("localhost", 27017);
            MongoDatabase database = mongoClient.getDatabase("MongoDB");
            
            pojo.setId("1");
            pojo.setName("ilkay");
            pojo.setSurname("günel");
        
            Document document = new Document();
            document.put("person", pojo);
        
            database.getCollection("Records").insertOne(document);  
        } catch (Exception e) {
            System.err.println("Bir Hata Meydana Geldi!");
            System.out.println("Hata" + e);
        }
    }
}

My Pojo is this:

package io.github.ilkgunel.mongodb;

public class Pojo {
    String name;
    String surname;
    String id;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getSurname() {
        return surname;
    }

    public void setSurname(String surname) {
        this.surname = surname;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    } 
}
1
  • For anybody getting this exception when querying Mongo, ensure you're querying with the correct datatype (e.g. String), not a POJO. Commented Jun 8, 2023 at 19:48

10 Answers 10

24

From the looks of what you are trying to do, you are trying to add some custom data type (in this case your POJO) but what you need to keep in mind is that fields in documents can only accept certain data types, not objects directly.

In case if you didn't know also, Mongo Documents are structured the same way as json. So you have to explicitaly create the documents by creating the fields and inserting the values into them. There are specific data types that are allowed in value fields:

http://mongodb.github.io/mongo-java-driver/3.0/bson/documents/

To help with your case, the code below takes your POJO as a parameter and knowing the structure of the POJO, returns a Mongo Document that can be inserted into your collection:

private Document pojoToDoc(Pojo pojo){
    Document doc = new Document();

    doc.put("Name",pojo.getName());
    doc.put("Surname",pojo.getSurname());
    doc.put("id",pojo.getId());

    return doc;
} 

This should work for insertion. If you want to index one of the fields:

database.getCollection("Records").createIndex(new Document("id", 1));

I hope this answers your question and works for you.

Sign up to request clarification or add additional context in comments.

Comments

11

You need to configure the CodeRegistry to use the PojoCodecProvider as explained here: http://mongodb.github.io/mongo-java-driver/3.7/driver/getting-started/quick-start-pojo/

1 Comment

Not sure if this option was available when the OP asked the question couple years back, but this is the best solution, since you are utilizing Mongo's builtin, rather than rolling your own.
9

To be bit abstract, as this may save the day for other developers..
This error: CodecConfigurationException: Can't find a codec for class xxx means that your mongo driver is not able to handle the data you sent in the object you made of that xxx class and accordingly can't generate the mongo query you want.

The resolution in that case would be either to use the right class i.e to use one of the expected classes by the driver (in my case replacing java array by ArrayList object resolved the issue).. The other resolution could be to upgrade your driver. Third solution could be as mentioned by @Renato, to define your own decoding logic.. This depends on your exact case.
hth

Comments

4

Use below set of lines while making connection to mongo db for resolving the issue with codec, while using POJO class in mongo.

Reference : https://developer.mongodb.com/quickstart/java-mapping-pojos

ConnectionString connectionString = new ConnectionString("mongodb://" + username + ":" + password + "@" + host + ":" + port);
CodecRegistry pojoCodecRegistry = fromProviders(PojoCodecProvider.builder().automatic(true).build());
CodecRegistry codecRegistry = fromRegistries(MongoClientSettings.getDefaultCodecRegistry(), pojoCodecRegistry);

MongoClientSettings clientSettings = MongoClientSettings.builder()
                .applyConnectionString(connectionString)
                .codecRegistry(codecRegistry)
                .build();
MongoClient mongoClient = MongoClients.create(clientSettings);
MongoDatabase mongoDatabase = mongoClient.getDatabase(database);

Comments

2

Documentation: MongoDB Driver Quick Start - POJOs

After following the above document, if you are still getting error, then

you could be using a generic document inside your collection like

class DocStore {
  String docId:
  String docType;
  Object document; // this will cause the BSON cast to throw a codec error
  Map<String, Object> document; // this won't
}

And still, you would want to cast your document from POJO to Map

mkyong tutorial could help.

As for the fetch, it works as expected but you might want to cast from Map to your POJO as a post-processing step, we can find some good answers here

Hope it helps! 🙂️

Comments

2

I had this problem with the spring boot. The code below solved the problem.

Creating beam.

@Configuration
@RequiredArgsConstructor
public class MongoConfig {

    private final MongodbProperties properties;

    @Bean
    public MongoClientSettings mongoClient() {
        return MongoClientSettings.builder()
                .applyToClusterSettings(builder -> builder.hosts(getServerAddress()))
                .credential(getClientCredentials())
                .codecRegistry(getCodecRegistry())
                .build();
    }

    private CodecRegistry getCodecRegistry() {
        return fromRegistries(MongoClientSettings.getDefaultCodecRegistry(),
                fromProviders(PojoCodecProvider.builder().automatic(true).build()));
    }

    private List<ServerAddress> getServerAddress() {
        return Collections.singletonList(new ServerAddress(properties.getHost(), properties.getPort()));
    }

    private MongoCredential getClientCredentials() {
        return MongoCredential
                .createCredential(properties.getUsername(), properties.getAuthenticationDatabase(),
                        properties.getPassword().toCharArray());
    }
}

Getting properties from application.yml file.

@Getter
@Setter
@Configuration
public class MongodbProperties {

    @Value("${spring.data.mongodb.host}")
    private String host;

    @Value("${spring.data.mongodb.database}")
    private String database;

    @Value("${spring.data.mongodb.authentication-database}")
    private String authenticationDatabase;

    @Value("${spring.data.mongodb.port}")
    private int port;

    @Value("${spring.data.mongodb.username}")
    private String username;

    @Value("${spring.data.mongodb.password}")
    private String password;
}

Comments

2

MongoDB driver couldn't understand your POJO, So it is asking for a way to convert it to the BSON document. So, Instead of defining codecs for each object, it is better to convert POJO into the document and use it further.

Just convert it using object mapper/ GSON and parse it using org.bson.Document class.

ObjectMapper objectMapper = new ObjectMapper(); //Advisable to create and consume as bean
Document pojoDocument = Document.parse(objectMapper.writeValueAsString(pojo));

Then you can fed the pojoDocument into the mongo client methods.

Document document = new Document();
document.put("person", pojoDocument);

database.getCollection("Records").insertOne(document); 

Comments

0

I'm using MongoDB POJO support. In my case, I had this "clue" WARNing before the exception:

 org.bson.codecs.pojo                     : Cannot use 'UserBeta' with the PojoCodec.

org.bson.codecs.configuration.CodecConfigurationException: Property 'premium' in UserBeta, has differing data types: TypeData{type=PremiumStatus} and TypeData{type=Boolean}.

My class UserBeta had getPremium(), setPremium(), and isPremium(). I already @BsonIgnore-d the isPremium() but for some reason it's still detected and causing conflict.

My workaround is to rename isPremium() to isAnyPremium().

Comments

0

I resolve it by adding the spring-boot-starter-data-mongodb dependency in your pom.xml or your build.gradle.

compile group: 'org.springframework.boot', name: 'spring-boot-starter-data-mongodb', version: '2.2.4.RELEASE'

Comments

-3

did you check the library of mongodb. I solve this problem in this morning by change the mongodb java driver from 3.2.2 to 3.4.2. the new maven like that:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-mongodb</artifactId>
    <version>1.5.4.RELEASE</version>
</dependency>

have a try and response

2 Comments

Still fails on mongodb-driver 3.6.4, so - no
This has nothing to do with what the PO asked. Your answer references drives but code shows spring framework, irrelevant to original question.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.