Issue Details (XML | Word | Printable)

Key: NUCCORE-540
Type: Bug Bug
Status: Closed Closed
Resolution: Fixed
Priority: Major Major
Assignee: Andy Jefferson
Reporter: Andy Jefferson
Votes: 0
Watchers: 2

If you were logged in you would be able to see more operations.
DataNucleus Core

ObjectManager currently attempts to cache objects that have no identity (embedded) causing attempted serialisation

Created: 03/Jun/10 08:11 AM   Updated: 08/Apr/12 05:33 PM   Resolved: 03/Jun/10 08:18 AM
Component/s: Cache
Affects Version/s: 2.0.4, 2.1.0.m1, 2.1.0.m2, 2.1.0.m3
Fix Version/s: 2.1.0.release

 Description  « Hide
No identity means don't even try to cache

Sort Order: Ascending order - Click to sort in descending order
Andy Jefferson added a comment - 03/Jun/10 08:18 AM
SVN trunk fixes this

Ales Justin added a comment - 16/Aug/10 03:12 PM
I've applied the NUCCONRE-540 to 1.1.5 branch (revision 7070),
but I still get the error:

java.lang.IllegalArgumentException: can't accept class org.datanucleus.identity.IdentityReference as a memcache entity
at org.datanucleus.cache.javaxcache.JavaxCacheLevel2Cache.evict(
at org.datanucleus.ObjectManagerImpl.performLevel2CacheUpdateAtCommit(
at org.datanucleus.ObjectManagerImpl.preCommit(
at org.datanucleus.TransactionImpl.internalPreCommit(
at org.datanucleus.TransactionImpl.commit(
at org.datanucleus.jpa.EntityTransactionImpl.commit(

As you can see it actually doesn't go into newly added code:

    private void performLevel2CacheUpdateAtCommit()
        // Lock the L2 cache so nobody else can have it while we are updating objects
        // Without this we can get race conditions between threads taking objects out, and
        // us putting objects in leading to assorted exceptions in AbstractStateManager or
        // in the PC object jdoReplaceField() methods.
        Level2Cache l2Cache = omf.getLevel2Cache();
        synchronized (l2Cache)
            // Process all modified objects adding/updating/removing from L2 cache as appropriate
            Iterator txCachedIter = txCachedIds.iterator();
            while (txCachedIter.hasNext())
                Object id =;
                StateManager sm = enlistedSMCache.get(id);
                if (sm == null)
                    // Modified object no longer enlisted so has been GCed, so remove from L2
                    if (NucleusLogger.CACHE.isDebugEnabled())
                            id, String.valueOf(l2Cache.getSize())));
                    l2Cache.evict(id); // <-- HERE

What would be the proper way to fix this?
(e.g. do we actually really need the NUCCORE-539?)

Ales Justin added a comment - 16/Aug/10 03:44 PM
Ah, let me just mention what I'm actually doing -- which is pretty simple.

EntityManager em = ...;
// begin its transaction
FooBar entity = new FooBar();
// commit or rollback

Yup, plain simple save.
Should this "// Modified object no longer enlisted so has been GCed, so remove from L2" really apply here?

Ales Justin added a comment - 17/Aug/10 02:04 PM
From this code

            Iterator txCachedIter = txCachedIds.iterator();
            while (txCachedIter.hasNext())
                Object id =;
                System.err.println("-------> " + id);
                StateManager sm = enlistedSMCache.get(id);

this is the id

id = {org.datanucleus.identity.IdentityReference@4423}
key: javax.jdo.identity.LongIdentity = {javax.jdo.identity.LongIdentity@4604}"2"

whereas the key is the only key in "enlistedSMCache" map.
If this is of any help ...

Ales Justin added a comment - 17/Aug/10 02:14 PM
The ids get replaced

     * Replace the previous object id for a persistable object with a new one.
     * This is used where we have already added the object to the cache(s) and/or enlisted it in the txn before
     * its real identity was fixed (attributed in the datastore).
     * @param pc The Persistable object
     * @param oldID the old id it was known by
     * @param newID the new id
    public synchronized void replaceObjectId(Object pc, Object oldID, Object newID)

        if (enlistedSMCache.get(oldID) != null)
            // Swap the enlisted object identity
            if (sm != null)
                enlistedSMCache.put(newID, sm);

but the one in the txCached remains the same -- hence no match.

Was this already fixed in some other JIRA issue?

Andy Jefferson added a comment - 19/Sep/10 08:25 PM
1.1 isn't supported. If you have some issue reproducible with 2.x then please attach a testcase

Ales Justin added a comment - 20/Sep/10 03:31 PM
Does some 2.x already work on AppEngine?

Andy Jefferson added a comment - 20/Sep/10 03:42 PM
Not that I'm aware of. AppEngine plugin is the responsibility of Google and not received communication from them on that plugin in some time (sadly); I got tired of asking when they planned on supporting 2.x a long time ago

Ales Justin added a comment - 20/Sep/10 03:56 PM
>> I got tired of asking when they planned on supporting 2.x a long time ago

Any idea what might be different from 1.x to 2.x wrt the issue?
Since afai looked, things look pretty much similar.

I can try to produce a simple test, since reproducing this is trivial: simple save/persist + use javax.cache impl with Serializable keys as a must.

Anton Kosyakov added a comment - 08/Apr/12 03:03 PM

I reproduced this bug on datanucleus 3.0.6.

I've upgraded appengine v.1.6.4 to datanucleus-appengine v2 and added datanucleus-cache-3.0.3.jar in war/WEB-INF/lib directory to enable "javax.cache" (GAE Memcache).

But when I tried to persist entity I got the following error:
java.lang.IllegalArgumentException: Cannot use as a key: 'org.datanucleus.identity.IdentityReference@7d27a2b6'
Caused by: org.datanucleus.state.JDOStateManager

Andy Jefferson added a comment - 08/Apr/12 05:33 PM
Hi, maybe you did but then that is not latest code, and you provide no testcase so consequently unreproduceable