surinder-insonix / datanucleus-appengine

Automatically exported from code.google.com/p/datanucleus-appengine
0 stars 0 forks source link

No longer able to get encoded key string primary key ID with "datanucleus gae.pk-id" immediately after saving #314

Open GoogleCodeExporter opened 8 years ago

GoogleCodeExporter commented 8 years ago
My problem
----------
I am porting my application from version 1.0.10 to 2.1.2 of the DataNucleus 
plug-in for GAE/J using the new 1.7.5 GAE/J SDK. This changes my JDO version 
from 2.3 to 3.0.1. My JDO persistent entity class has a primary key of type 
encoded string, along with read-only access to the object’s numeric ID. Each 
instance is the sole member of its entity group (children and parent are linked 
by numeric ID only).

Using the previous version 1.0.10 of the DataNucleus plug-in, I was able to 
create and persist a new entity instance and then immediately access its 
numeric ID.

Using version 2.1.2 of the DataNucleus plug-in, I find that the new 
instance’s numeric ID is not available immediately after persistence (even 
after a 5 second sleep of the current thread) – even though it is generated 
and stored, and is available some time later later. This access was not using 
an object returned by a query nor an object returned by a 
find-by-encoded-key-string but via an object returned by:

  PersistenceManager#makePersistent(...);

The above behaviour change occurs using the development web server. I have not 
tried this in production since my datastore data exchange testing (and any 
required re-working) is incomplete.

Persistent entity class code extract
------------------------------------
    @PersistenceCapable(identityType = IdentityType.APPLICATION, detachable = "true")
    public class MyEntity implements Serializable
    {
      private static final long serialVersionUID = 1L;

      // No setter for this read-only data member
      @PrimaryKey
      @Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
      @Extension(vendorName="datanucleus", key="gae.encoded-pk", value="true")
      private String sEncodedKey;

      // No setter for this read-only data member
      @Persistent
      @Extension(vendorName="datanucleus", key="gae.pk-id", value="true")
      private Long loID;

      @Persistent
      private Long loParentID;

      //
      // Other persistent data members
      //

      public Long getID()
      {
        return loID;
      }

      //
      // Other getters and setters
      //
    }

Persistence code
----------------
private static final Object objLock = new Object();

public static MyEntity createMyEntityChild(Long loParentID, String sChildName)
{
  MyEntity meResult = null;

  synchronized(objLock)
  {
    MyEntity mePersistedChild = null;
    MyEntity meParent = findMyEntityByID(null, loParentID);    // My own method

    PersistenceManagerFactory pmf =
     DataExchange.getPersistenceManagerFactory();    // My own method

    PersistenceManager pm = pmf.getPersistenceManager();
    Transaction tx = pm.currentTransaction();
    try
    {
      tx.begin();

      if ((meParent != null) && meParent.getActive())
      {
        MyEntity meChild = new MyEntity();
        meChild.setParentID(loParentID);
        meChild.setName(sChildName);
        meChild.setActive(true);
        mePersistedChild = pm.makePersistent(meChild);

        ...
      }

      // mePersistedChild.getEncodedKey() is populated
      // mePersistedChild.getID()         is null

      tx.commit();

      // mePersistedChild.getEncodedKey() is populated
      // mePersistedChild.getID()         is null
    }
    finally
    {
      try
      {
        if (tx.isActive())    // Because of an exception, say
          tx.rollback();
      }
      finally
      {
        pm.close();
      }
    }

    long LO_PERSISTENCE_SLEEP_INTERVAL_MS = 5000L;
    // My own method to sleep this thread so many milliseconds
    MiscellaneousBusiness.sleep(LO_PERSISTENCE_SLEEP_INTERVAL_MS);

    // mePersistedChild.getEncodedKey() is populated
    // mePersistedChild.getID()         is null

    ...
  }

  return meResult;
}

Software environment
--------------------
  Web server: Google App Engine for Java version 1.7.5
  Web framework: Apache Wicket 6.6.0
  Java version: 1.6.0_41; Java HotSpot(TM) Client VM 20.14-b01
  GAE/J DataNucleus plug-in version: 2.1.2
  DataNucleus Access Platform version: 3.1.3
  JDO version: 3.0.1
  Operating system: Microsoft Windows XP version 5.1 running on x86
  IDE: NetBeans 7.2 (build 201207171143)

Miscellaneous information
-------------------------
The StackOverflow post at 
http://stackoverflow.com/questions/15065552/unable-to-get-id-of-newly-created-jd
o-persistent-entity-using-gae-j-datanucleus refers.

I had already raised this issue as GAE issue 8925 (No longer able to get 
encoded key string primary key ID immediately after saving) at: 
code.google.com/p/googleappengine/issues/detail?id=8925. I am told that this is 
the better place to raise this issue.

(Can/should this issue tracker be re-publicised on the Google Developers GAE 
home page? The sole issue tracker that I can see linked on that page is the 
googleappengine issue tracker.)

Original issue reported on code.google.com by IanMarsh...@gmail.com on 4 Mar 2013 at 11:15

GoogleCodeExporter commented 8 years ago
I confirm that this issue also occurs in production.

A few minutes after creating and persisting entities (of the class as described 
in the original post above) the encoded key string primary key ID remains 
unavailable. However, after 30 minutes this ID is available.

(This mirrors behaviour using the development web application server where, 
after a delay of the order of 10 to the power 1 minutes, the ID becomes 
available.)

Original comment by IanMarsh...@gmail.com on 1 Apr 2013 at 3:38