views:

1760

answers:

2

I'm using the Google AppEngine, with Java. When I use some datastore features, I'm getting an error message:

Object with id "edvaltt.Teacher@64064b" is managed by a different Object Manager

I don't know what this means or how to fix it or where to look for documentation on this error. Can anyone help me? The code I'm using is:

@PersistenceCapable(identityType = IdentityType.APPLICATION)
public class School {
@PrimaryKey
@Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
private String shortname;

@Persistent
private String fullname;

@Persistent
@Order(extensions = @Extension(vendorName="datanucleus", key="list-ordering", value="code asc"))
private List<Teacher> Teachers;

...

public Teacher FindOrCreateTeacher(String code)
{
    // Can we find the teacher without any database code?
    Teacher newTeacher = FindTeacher(code);
    if (newTeacher != null)
        return newTeacher;

    // Create the teacher:
    PersistenceManager pm = PMF.get().getPersistenceManager();
    Transaction tx = pm.currentTransaction();
    try {
        tx.begin();
        for (Teacher teacher : Teachers) {
         if (teacher.getCode() == code) {
          tx.rollback();
          return teacher;
         }
        }
        newTeacher = new Teacher(code);
        Teachers.add(newTeacher);
        pm.makePersistent(newTeacher);
        pm.makePersistent(Teachers);
        tx.commit();
    } finally {
        tx.commit();
    }
    return newTeacher;
}

I believe that "private List<Teacher> Teachers;" refers to an "owned, one to many" relationship.

+2  A: 

As illustrated in this ticket, shouldn't you close the pm (PersistenceManager)?

} finally {
    tx.commit();
    pm.close();
}
VonC
I originally thought that this had solved my problem, but it doesn't. For a start, I still don't know what is going on and why closing of the persistence manager is necessary, or when it should be done. Secondly, the AppEngine documentation encourages use of a singleton pattern with the PersistenceManager, and pm.close() would mean that you can't do anything more with the Google datastore for the remainder of the process.
Tim Cooper
Singleton pattern with the PMF, not the PM. pm.close() *not* pmf.close()
DataNucleus
+5  A: 

A persistent object can only be "managed" by one PersistenceManager. In DataNucleus this is backed internally by an "ObjectManager". The message says that you are trying to associate an object managed by one PM with a different PM. You can easily debug that by printing out the PM for each (persistent) object

JDOHelper.getPersistenceManager(obj);

Since you don't define where the message comes from, not much more can be said. The DataNucleus log entries would tell you way way more than that.

Closing the PM is always an essential thing to do (unless you want resource leaks)

DataNucleus
Interesting explanation. +1
VonC
Can you further explain to me what is a suitable lifetime for a PM instance? Suppose I'm writing a web app. Should I open and close it on every page request? Or keep one instance open for the lifetime of the process? (If I commit a transaction but don't close the PM, does this mean the worst that happens is a memory leak? I mean, my data is safe?)
Tim Cooper
How long is the process ? A typical web system would use a PM per request. Creating a PM is not expensive (creating a PMF *is* expensive). If using txns then you can safely leave a PM open ... as long as you aren't performing non-transactional updates also with that PM.
DataNucleus