Search code examples
google-app-enginetransactionsgoogle-cloud-datastorejdo

Google App Engine & JDO: Transaction is not written to the datastore


We are using GAE with JDO2.3 and have this code:

public void submit_job (HttpSession session, BlobKey blobKey) throws Exception {
  // START TRANSACTION
  PersistenceManager pm = PMF.get().getPersistenceManager();
  Transaction tx = pm.currentTransaction();
  tx.begin();

  // GET JOB AND MEMBER FROM DATASTORE
  Key jobKey = (Key)session.getAttribute("jobkey");
  String userName = session.getAttribute("username").toString();

  Job job = pm.getObjectById(Job.class, jobKey);
  Member m = pm.getObjectById(Member.class, username);

  // STORE JOB INFORMATION IN DATASTORE
  Date now = new Date();
  job.caricature = blobKey;
  job.whenSubmitted = now;
  job.whenFinished = now;
  pm.makePersistent(job);
  pm.flush();
  log.warning("submit_job: updating job " + job.key);

  // UPDATE MEMBER INFORMATION
  m.numSubmittedJobs++;
  pm.makePersistent(m);
  pm.flush();    
  log.warning("submit_job: updating user " + username);

  // COMPLETE TRANSACTION
  tx.commit();
  pm.close();
  log.warning("transaction completed? " + !tx.isActive());
}

The symptoms:

  • no exception is thrown, everything runs fine
  • at the end, the transaction is properly completed ("transaction completed? true")
  • following queries can read the updated data from the Member and Job objects

BUT

  • the information does not show up in the datastore manager
  • after restarting the instance, the JDO objects have their old values. ALL CHANGES ARE LOST.

Here is our jdoconfig.xml:

<?xml version="1.0" encoding="utf-8"?>
<jdoconfig xmlns="http://java.sun.com/xml/ns/jdo/jdoconfig"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:noNamespaceSchemaLocation="http://java.sun.com/xml/ns/jdo/jdoconfig">

   <persistence-manager-factory name="transactions-optional">
       <property name="javax.jdo.PersistenceManagerFactoryClass"
           value="org.datanucleus.api.jdo.JDOPersistenceManagerFactory"/>
       <property name="javax.jdo.option.ConnectionURL" value="appengine"/>
       <property name="javax.jdo.option.NontransactionalRead" value="true"/>
       <property name="javax.jdo.option.NontransactionalWrite" value="true"/>
       <property name="javax.jdo.option.RetainValues" value="true"/>
       <property name="datanucleus.appengine.autoCreateDatastoreTxns" value="true"/>
       <property name="datanucleus.appengine.singletonPMFForName" value="true"/>
       <property name="datanucleus.appengine.datastoreEnableXGTransactions" value="true"/>
   </persistence-manager-factory>
</jdoconfig>

and the persistence.xml:

<?xml version="1.0" encoding="UTF-8" ?>
<persistence
    xmlns="http://java.sun.com/xml/ns/persistence"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"
    version="1.0">

    <persistence-unit name="transactions-optional">
        <provider>org.datanucleus.api.jpa.PersistenceProviderImpl</provider>
        <properties>
            <property name="datanucleus.NontransactionalRead" value="true"/>
            <property name="datanucleus.NontransactionalWrite" value="true"/>
            <property name="datanucleus.ConnectionURL" value="appengine"/>
        </properties>
    </persistence-unit>
</persistence>

Any help is appreciated, we already put a lot of effort into this topic, but are unable to solve it yet.

Thanks!


Solution

  • So you're setting public fields of a persistable class, and somehow expect the persistence mechanism to know about this. As per the JDO spec, you should use setters, or annotate the class doing the setting as PersistenceAware.

    And look at the log too, since it tells you what is happening