Reputation: 21
I am using Spring data connect to mongodb. Please see my problems below:
Now, I have two data models (User and Draft):
@Document
public class User implements Serializable {
@Id
private String id;
private String showName;
private String password;
//..... (other attributes)
@DBRef
private List<Draft> createdDraft = new ArrayList<Draft>();
//constructors
public User() {
super();
}
public User(String id, String showName, String password, //....other attributes
List<Draft> createdDraft) {
super();
this.id = id;
this.showName = showName;
this.password = password;
//....
}
//getters and setters
}
and
@Document
public class Draft {
@Id
private String id;
private String title;
private Date createTime;
private Date lastEditTime;
@DBRef
private User lastEditor;
@DBRef
private User mainAuthor;
@DBRef
private List<User> coAuthors = new ArrayList<User>();
private String externalURL;
//constructors..
public Draft() {
super();
}
public Draft(String id, String title, Date createTime, Date lastEditTime,
User lastEditor, User mainAuthor, String externalURL) {
super();
this.id = id;
this.title = title;
this.createTime = createTime;
this.lastEditTime = lastEditTime;
this.lastEditor = lastEditor;
this.mainAuthor = mainAuthor;
this.externalURL = externalURL;
}
//getters and setters...
}
In my project, I have created the user successfully then, I would like to add a draft to the existing user.
public String CreateNewDraft(User mainAuthor)
{
Draft draft = new Draft();
draft.setMainAuthor(mainAuthor);
Date now = new Date(System.currentTimeMillis());
draft.setCreateTime(now);
mainAuthor.getCreatedDraft().add(draft);
//insert the draft --> Successful (1)
mongoOps.insert(draft);
//update the user --> Successful (2)
mongoOps.save(mainAuthor);
//find the last inserted draft. --> Errors.
Draft d = mongoOps.findOne(query(where("createTime").is(now) ), Draft.class);
return d.getId()
}
In (1), I have found a new "draft" document created in mongoDB, which has _id = it has 52a1591597d738f7b397be96.
In (2), I have found the existing user (mainAuhtor) document has one entry added in the createdDraft field like [ { "$ref" : "draft" , "$id" : { "$oid" : "52a1591597d738f7b397be96"}}]
Exception & log:
processing failed; nested exception is java.lang.StackOverflowError org.springframework.web.servlet.DispatcherServlet. doDispatch(DispatcherServlet.java:972) org.springframework.web.servlet.DispatcherServlet. doService(DispatcherServlet.java:852) org.springframework.web.servlet.FrameworkServlet.p rocessRequest(FrameworkServlet.java:882) org.springframework.web.servlet.FrameworkServlet.d oGet(FrameworkServlet.java:778) javax.servlet.http.HttpServlet.service(HttpServlet .java:621) javax.servlet.http.HttpServlet.service(HttpServlet .java:728) org.apache.tomcat.websocket.server.WsFilter.doFilt er(WsFilter.java:51)
root cause
java.lang.StackOverflowError java.net.SocketInputStream.socketRead0(Native Method) java.net.SocketInputStream.read(Unknown Source) java.net.SocketInputStream.read(Unknown Source) java.io.BufferedInputStream.fill(Unknown Source) java.io.BufferedInputStream.read1(Unknown Source) java.io.BufferedInputStream.read(Unknown Source) org.bson.io.Bits.readFully(Bits.java:46) org.bson.io.Bits.readFully(Bits.java:33) org.bson.io.Bits.readFully(Bits.java:28) com.mongodb.Response.<init>(Response.java:40) com.mongodb.DBPort.go(DBPort.java:124) com.mongodb.DBPort.call(DBPort.java:74) com.mongodb.DBTCPConnector.innerCall(DBTCPConnecto r.java:286) com.mongodb.DBTCPConnector.call(DBTCPConnector.jav a:257) com.mongodb.DBApiLayer$MyCollection.__find(DBApiLa yer.java:310) com.mongodb.DBApiLayer$MyCollection.__find(DBApiLa yer.java:295) com.mongodb.DBCollection.findOne(DBCollection.java :346) com.mongodb.DBCollection.findOne(DBCollection.java :331) com.mongodb.DBRefBase.fetch(DBRefBase.java:53) org.springframework.data.mongodb.core.convert.Mapp ingMongoConverter.readValue(MappingMongoConverter. java:1046) org.springframework.data.mongodb.core.convert.Mapp ingMongoConverter.access$100(MappingMongoConverter .java:77) org.springframework.data.mongodb.core.convert.Mapp ingMongoConverter$MongoDbPropertyValueProvider.get PropertyValue(MappingMongoConverter.java:999) org.springframework.data.mongodb.core.convert.Mapp ingMongoConverter.getValueInternal(MappingMongoCon verter.java:755) org.springframework.data.mongodb.core.convert.Mapp ingMongoConverter$2.doWithAssociation(MappingMongo Converter.java:265) org.springframework.data.mapping.model.BasicPersis tentEntity.doWithAssociations(BasicPersistentEntit y.java:269) org.springframework.data.mongodb.core.convert.Mapp ingMongoConverter.read(MappingMongoConverter.java: 262) org.springframework.data.mongodb.core.convert.Mapp ingMongoConverter.read(MappingMongoConverter.java: 223) org.springframework.data.mongodb.core.convert.Mapp ingMongoConverter.readCollectionOrArray(MappingMon goConverter.java:788) org.springframework.data.mongodb.core.convert.Mapp ingMongoConverter.readValue(MappingMongoConverter. java:1048) org.springframework.data.mongodb.core.convert.Mapp ingMongoConverter.access$100(MappingMongoConverter .java:77) org.springframework.data.mongodb.core.convert.Mapp ingMongoConverter$MongoDbPropertyValueProvider.get PropertyValue(MappingMon```
Can someone help me to take a look? Thanks so much!
Upvotes: 2
Views: 5386
Reputation: 11
I was also facing this issue while querying data from mongo. In my case, it was a dataType mismatch, I was using org.joda.DateTime to query on a document field of type java.time.LocalDateTime.
For anyone facing such issue, please just have a look in this direction as well
Upvotes: 0
Reputation: 31
you should map your received entity (document) from the mongo database..
use the Springs Converter interface
for example:
public class ProfileReadConverter implements Converter<DBObject, Profile> {
@Override
public Profile convert(DBObject source) {
@SuppressWarnings("unchecked")
Profile p = new Profile((ObjectId) source.get("_id"), (boolean) source.get("active"), (String) source.get("name"),
(String) source.get("shortName"), (List<Person>) source.get("person"));
return p;
}
}
Profile.java
@Document(collection = "profile")
public class Profile {
@Id
private ObjectId id;
private boolean active;
@Indexed(unique = true)
@Field("ProfileName")
private String name;
private String shortName;
@DBRef
private List<Person> person = new ArrayList<Person>();
public Profile() {
}
@PersistenceConstructor
public Profile(ObjectId id, boolean active, String name, String shortName, List<Person> person,) {
this.id = id;
this.active = active;
this.name = name;
this.shortName = shortName;
this.person = person;
}
//getter and setter
Person.java
@Document(collection = "person")
public class Person extends Ressource {
@Indexed
private String firstname;
private String lastname;
@Field("email")
@Indexed(unique = true)
private String eMailAddress;
private String login;
@DBRef
private List<Profile> profiles = new ArrayList<Profile>();
public Person(ObjectId id, String firstname, String lastname, String eMailAddress, String login) {
this.setId(id);
this.firstname = firstname;
this.lastname = lastname;
this.eMailAddress = eMailAddress;
this.login = login;
}
@PersistenceConstructor
public Person(ObjectId id, String firstname, String lastname, String eMailAddress, String login,
List<Profile> profiles) {
this.firstname = firstname;
this.lastname = lastname;
this.eMailAddress = eMailAddress;
this.login = login;
this.profiles = profiles;
}
main or test class
...
Profile profileFind = mongoOps.findOne(new Query(where("shortName").is("SE")), Profile.class, "profile");
Upvotes: 0
Reputation: 15076
This is a bug (or expected behaviour?) of spring data mongodb (I get this in 1.3.x version, haven't tried 1.4.x).
The problem is that User has reference to Draft and Draft to the same user instance so the converter gets into infinite loop.
@Document
public class User implements Serializable {
...
@DBRef
private List<Draft> createdDraft = new ArrayList<Draft>();
and
@Document
public class Draft {
...
@DBRef
private User lastEditor;
@DBRef
private User mainAuthor;
@DBRef
private List<User> coAuthors = new ArrayList<User>();
You should probably use simple id references, not DBRef (it is even suggested here http://docs.mongodb.org/manual/reference/database-references/ as suitable for most use cases)
If you find yourself using DBRef a lot you should consider using different kind of database, e.g. a graph database.
Upvotes: 3