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
Operations

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 com.google.appengine.api.memcache.MemcacheSerialization.serialize(MemcacheSerialization.java:262)
at com.google.appengine.api.memcache.MemcacheSerialization.makePbKey(MemcacheSerialization.java:199)
at com.google.appengine.api.memcache.MemcacheServiceImpl.get(MemcacheServiceImpl.java:274)
at com.google.appengine.api.memcache.stdimpl.GCache.remove(GCache.java:175)
at org.datanucleus.cache.javaxcache.JavaxCacheLevel2Cache.evict(JavaxCacheLevel2Cache.java:192)
at org.datanucleus.ObjectManagerImpl.performLevel2CacheUpdateAtCommit(ObjectManagerImpl.java:2982)
at org.datanucleus.ObjectManagerImpl.preCommit(ObjectManagerImpl.java:2925)
at org.datanucleus.TransactionImpl.internalPreCommit(TransactionImpl.java:369)
at org.datanucleus.TransactionImpl.commit(TransactionImpl.java:256)
at org.datanucleus.jpa.EntityTransactionImpl.commit(EntityTransactionImpl.java:104)
at org.datanucleus.store.appengine.jpa.DatastoreEntityTransactionImpl.commit(DatastoreEntityTransactionImpl.java:55)

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 = txCachedIter.next();
                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())
                    {
                        NucleusLogger.CACHE.debug(LOCALISER.msg("004014",
                            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();
em.persist(entity);
// 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 = txCachedIter.next();
                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.remove(oldID);
                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
Hi!

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: java.io.NotSerializableException: 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