0

I am brand new to MongoDB, so sorry if the question is basic.

I am trying to get a basic CRUD working with Java basic objects (POJOs), but this code fails. (What is the correct way of doing this? I think it might be close to this):

BasicDBObject document = new BasicDBObject();
document.put("name", user);
dbCollection.insert(document);

This is the message I am getting:

Exception in thread "main" java.lang.IllegalArgumentException: can't serialize class entities.users.NormalUser
    at org.bson.BasicBSONEncoder._putObjectField(BasicBSONEncoder.java:270)
    at org.bson.BasicBSONEncoder.putObject(BasicBSONEncoder.java:174)
    at org.bson.BasicBSONEncoder.putObject(BasicBSONEncoder.java:120)
    at com.mongodb.DefaultDBEncoder.writeObject(DefaultDBEncoder.java:27)
    at com.mongodb.OutMessage.putObject(OutMessage.java:289)
    at com.mongodb.DBApiLayer$MyCollection.insert(DBApiLayer.java:261)
    at com.mongodb.DBApiLayer$MyCollection.insert(DBApiLayer.java:226)
    at com.mongodb.DBCollection.insert(DBCollection.java:75)
    at com.mongodb.DBCollection.insert(DBCollection.java:59)
    at com.mongodb.DBCollection.insert(DBCollection.java:104)
    at repositories.UsersRepository.createUser(UsersRepository.java:53)
    at repositories.UsersRepository.main(UsersRepository.java:90)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)
Community
  • 1
  • 1
stack man
  • 2,303
  • 9
  • 34
  • 54
  • Could you please add some details of user class / variable definition? – notionquest Sep 09 '16 at 12:23
  • @notionquest Sure, I will update the question shortly, thanks – stack man Sep 09 '16 at 12:27
  • @notionquest You can check them here actually. Please let me know if you need more info http://stackoverflow.com/questions/39397029/illegalargumentexception-can%C2%B4t-serialize-class-even-it-implements-serializable – stack man Sep 09 '16 at 12:28
  • 1
    The attributes Gender and Role could create serialize issue. Please can you try inserting doc without those two attributes for testing purpose? – notionquest Sep 09 '16 at 12:34
  • @notionquest I got rid of those attributes, but the problem remains – stack man Sep 09 '16 at 12:44

3 Answers3

1

You cannot simply serialize every class you have in your application with the mongo java driver. Either, you stick to JSON documents and their supported data types (basically string, various numbers, boolean, date) or you actually write a custom codec for your class, so that the internal Bson conversion can work with it.

Only link I found to a basic example unfortunately in German: https://dev-tek.de/lexicon/Entry/64-MongoDB-Anleitung-Custom-codecs-mit-Hilfe-des-DocumentCodecs/ - but maybe the code helps to understand.

Addendum, regarding the comment:

Basically, you can do a conversion yourself manually along the lines of:

Document doc = new org.bson.Document();
doc.put("userName", user.getName());
doc.put("userId", user.getID());
// ... or whatever your user object looks like
// and then:
dbCollection.insert(doc);

Then, you could try external encoding libraries for converting your object to JSON, for example Jackson as detailed in the answer of this question: Converting Java objects to JSON with Jackson

Once you have a JSON string, you can convert it to an org.bson.Document via

org.bson.Document.parse(jsonString)

and write this into the database.

Community
  • 1
  • 1
mtj
  • 3,381
  • 19
  • 30
1

Try using MongoTemplate. Save the java object in mongodb using this template, it will get created in a document form.

https://www.mkyong.com/mongodb/spring-data-mongodb-insert-document/

Example

MongoTemplate mongoTemplate = new MongoTemplate(new MongoClient("<server>"),"<db name>");

User user = new NormalUser();
mongoTemplate.save(user, "<collection>");
Prateek Mehta
  • 488
  • 1
  • 8
  • 15
1

Here is the detailed analysis on this issue:-

Looks like "lombok" library adds the boilerplate code (i.e. getter and setter methods for the attributes) during compilation time. I have observed two behaviors while executing the program.

1) Eclipse behavior:-

When I run the program via IDE (e.g. eclipse), the "getter" and "setter" methods were not getting generated. I have got serialization error when I ran the main class. I have decompiled the classes User and NormalUser and checked the content. It doesn't have the "getter" and "setter" methods.

Online Java Decompiler

2) Maven behavior:-

I have used maven commands to build the project and checked the classes User and NormalUser. This time I can see the boilerplate codes being generated. I have executed my Main class and it worked fine.

Solution:-

MongoClient client = new MongoClient();
        MongoDatabase database = client.getDatabase("localhost");
        MongoCollection<Document> normalUserCollection = database.getCollection("normaluser");

        User normalUser = new NormalUser("jack", "mike", "US", "dni", "123", Gender.MALE);

        Document document = new Document();
        document.put("user", document.parse(new ObjectMapper().writeValueAsString(normalUser)));

Mongo Java Driver used:-

<dependency>
    <groupId>org.mongodb</groupId>
    <artifactId>mongo-java-driver</artifactId>
    <version>3.2.2</version>
</dependency>
<dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.7.5</version>
        </dependency>

Output:-

The document has been inserted successfully in MongoDB collection.

{
    "_id" : ObjectId("57d2e4134c1c7b287cde1d30"),
    "user" : {
        "surname" : "mike",
        "address" : "US",
        "dni" : "dni",
        "bankAccount" : "123",
        "admin" : false,
        "name" : "jack",
        "gender" : "MALE"
    }
}
notionquest
  • 37,595
  • 6
  • 111
  • 105
  • Thanks a lot for such detailed respone. At the end, I managed to get it working with a slightly different way. Could you please let me know the dependency for "writeValueAsString"? Thanks again pal. – stack man Sep 10 '16 at 10:30