My suspicion is that in the update case you are starting your txn with a
PersistenceManager, then using a different PersistenceManager to load the
TextEntry (diaryManager.getTextEntryById().  I can't be sure because you
haven't posted the code for diaryManager, but if it does the same thing as
lookupTextChapterById() and pmp.get() creates a new PersistenceManager, then
this is probably what is going on.  You're not seeing the updates when you
commit the txn because the txn is not associated with the PersistenceManager
that loaded the TextEntry.  I'd recommend using the same PersistenceManager
for all these operations.

Hope this helps,
Max

On Sun, Nov 29, 2009 at 4:00 PM, Stevko <andy.ste...@gmail.com> wrote:

> I'm struggling with a JDO data loss situation.
> The code below will NEW a  TextEntry object and hook it into the
> object tree just fine.
> The copy DTO updates are performed without error/exception thrown but
> all updates are lost.
> The fields that are being lost are privateComment, byLine,
> shortContent, longContent, longContentSize.
>
> I've attached a DN transaction log at the bottom.
> The object state is marked as 'dirty' but the ObjectManager does not
> 'put' the new string values.
> According to the logs, for some unknown reason, the DB
> DatastorePersistenceHandler commits the "new"  object prior to the
> copy of the associated data from the action DTO into the persistent
> object.
>
> I've broken this up into two sequential transactions complete with
> isolated lookups but the data loss continues.
>
> //-------------------------------------
> // abridged code - error checking removed...
> //
> private final Provider<PersistenceManager> pmp;
> private PersistenceManager pm;
>
> @Override
> public SaveTextEntryResult execute(SaveTextEntry action,
>                ExecutionContext context) throws ActionException {
>
>        String entryId = action.getEntryId();
>        SaveTextEntryResult result;
>        try {
>                pm = pmp.get();
>                pm.currentTransaction().begin();
>
>                TextEntry entry;
>
>                // ----------
>                // is this new or update?
>                if (action.isNewEntry()) {
>
>                        // lookup the chapterid and verify accountid
>                        TextChapter chapter =
> diaryManager.lookupTextChapterById(action
>                                        .getChapterId());
>                        entry = new TextEntry(action.getTimestamp(),
> chapter,
>                                                action.getSourceType(),
> action.getSourceId());
>
>                } else {
>                        // look up the textentry id
>                        entry =
> diaryManager.lookupTextEntryById(action.getEntryId());
>                }
> //---->>> new object is flushed here <<<------
>                // copy fields from action to object
>                entry.setPrivateComment(action.isPrivateComment());
>                entry.setByLine(action.getByLine());
>                logger.info("SaveTextEntry() short content =" +
> action.getShortContent() );
>                entry.setShortContent(action.getShortContent());
>                logger.info("SaveTextEntry() long content =" +
> action.getLongContent
> () );
>                entry.setLongContent(action.getLongContent());
>
> //---->>> persist object updates are not flushed here  <<<------
>                pm.currentTransaction().commit();
>
>                result = new SaveTextEntryResult(true, entry.getId() );
>
>        } finally {
>
>                if (pm.currentTransaction().isActive()) {
>                        logger.severe("SaveTextEntry caught exception");
>                        result = new SaveTextEntryResult(false, "");
>                        pm.currentTransaction().rollback();
>                }
>        }
>
>        return result;
> }
> //------------
> // related method below
>        public TextChapter lookupTextChapterById(String id) {
>                pm = pmp.get();
>
>                TextChapter chapter = pm.getObjectById(TextChapter.class,
> id);
>
>                return (chapter);
>        }
>
> //----------------------------------------------------------------
> // Persistent object definition (bean methods removed)
>
> @PersistenceCapable(identityType = IdentityType.APPLICATION )
> @FetchGroup(  name="children", members={
>        @Persistent(name="commentEntrys"),
>        @Persistent(name="chapter")
> })
> public class TextEntry implements Entry, Serializable,
> Comparable<TextEntry> {
>
> @PrimaryKey
> @Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
> @Extension(vendorName = "datanucleus", key = "gae.encoded-pk", value =
> "true")
> private String id;
>
> @Persistent
> private Long accountId = new Long(0);
>
> // Parent collection with ArrayList<TextEntry>
> @Persistent
> private TextChapter chapter;
>
> @Persistent
> private Long timestamp = new Long(0);
>
> @Persistent
> private boolean privateComment = false;
>
> @Persistent
> private String byLine = "";
>
> @Persistent(defaultFetchGroup="true")
> private SourceType source = SourceType.UNKOWN;
>
> @Persistent
> private String sourceId = "";
>
> @Persistent(defaultFetchGroup="true")
> private String shortContent = null;
>
> @Persistent(defaultFetchGroup="true")
> private String longContentString = null;
>
> @Persistent(defaultFetchGroup="true")
> private Long longContentSize = new Long(-1);
>
> @Persistent(mappedBy = "textEntry")
> @Order(column="TEXTENTRY_COMMENTENTRY_IDX")
> private TreeSet< CommentEntry> commentEntrys = new TreeSet<
> CommentEntry>();
>
> public TextEntry(Long timestamp, TextChapter chapter,  SourceType
> source,
>                String sourceId) {
>        this.timestamp = timestamp;
>        this.source = source;
>        this.sourceId = sourceId;
>
>        // setup external references
>        this.chapter = chapter;
>        this.accountId = chapter.getAccountId();
>        chapter.add(this);
> }
>
>
> //-------------------------------------------------------------------------------------------------------
> // this is a log showing the point where the
> DatastorePersistenceHandler commits the fields.
>
> Nov 29, 2009 9:45:58 PM org.datanucleus.ObjectManagerImpl
> persistObjectInternal
> FINE: Making object persistent :
> "com.ninuku.diary2.server.diary.texten...@13c7edf"
> Nov 29, 2009 9:45:58 PM
> org.datanucleus.store.appengine.DatastorePersistenceHandler put
> FINE: Putting entity of kind TextEntry with key Diary(4)/TextChapter
> (7)/TextEntry(no-id-yet)
> Nov 29, 2009 9:45:58 PM
> org.datanucleus.store.appengine.DatastorePersistenceHandler put
> FINE:   timestamp : 1259531142320
> Nov 29, 2009 9:45:58 PM
> org.datanucleus.store.appengine.DatastorePersistenceHandler put
> FINE:   TEXTCHAPTER_TEXTENTRY_IDX : 7
> Nov 29, 2009 9:45:58 PM
> org.datanucleus.store.appengine.DatastorePersistenceHandler put
> FINE:   accountId : 2
> Nov 29, 2009 9:45:58 PM
> org.datanucleus.store.appengine.DatastorePersistenceHandler put
> FINE:   shortContent : null
> Nov 29, 2009 9:45:58 PM
> org.datanucleus.store.appengine.DatastorePersistenceHandler put
> FINE:   source : USER_MANUAL
> Nov 29, 2009 9:45:58 PM
> org.datanucleus.store.appengine.DatastorePersistenceHandler put
> FINE:   longContentSize : -1
> Nov 29, 2009 9:45:58 PM
> org.datanucleus.store.appengine.DatastorePersistenceHandler put
> FINE:   privateComment : false
> Nov 29, 2009 9:45:58 PM
> org.datanucleus.store.appengine.DatastorePersistenceHandler put
> FINE:   byLine :
> Nov 29, 2009 9:45:58 PM
> org.datanucleus.store.appengine.DatastorePersistenceHandler put
> FINE:   longContentString : null
> Nov 29, 2009 9:45:58 PM
> org.datanucleus.store.appengine.DatastorePersistenceHandler put
> FINE:   sourceId : 1259531142320
> Nov 29, 2009 9:45:58 PM org.datanucleus.sco.backed.TreeSet <init>
> FINE: Object "com.ninuku.diary2.server.diary.texten...@13c7edf" field
> "commentEntrys" is replaced by a SCO wrapper of type
> "org.datanucleus.sco.backed.TreeSet" [cache-values=true, lazy-
> loading=true, queued-operations=false, allow-nulls=false]
> Nov 29, 2009 9:45:59 PM
> org.datanucleus.store.appengine.DatastorePersistenceHandler get
> FINE: Getting entity of kind Diary with key Diary(4)
> Nov 29, 2009 9:46:22 PM
> com.google.appengine.api.datastore.dev.LocalDatastoreService
> $PersistDatastore persist
> INFO: Time to persist datastore: 10 ms
> Nov 29, 2009 9:46:32 PM
> com.ninuku.diary2.server.handler.SaveTextEntryHandler execute
> INFO: SaveTextEntry() short content =this is a short content update
> Nov 29, 2009 9:46:37 PM
> com.ninuku.diary2.server.handler.SaveTextEntryHandler execute
> INFO: SaveTextEntry() long content =this is a long content update
> Nov 29, 2009 9:46:40 PM org.datanucleus.TransactionImpl
> internalPreCommit
> FINE: Transaction committing for ObjectManager
> org.datanucleus.objectmanageri...@beef49
> Nov 29, 2009 9:46:40 PM org.datanucleus.ObjectManagerImpl
> flushInternal
> FINE: ObjectManager internalFlush() process started - 0 dirty objects
> Nov 29, 2009 9:46:40 PM org.datanucleus.ObjectManagerImpl
> flushInternal
> FINE: ObjectManager internalFlush() process finished
> Nov 29, 2009 9:46:40 PM org.datanucleus.transaction.Transaction commit
> FINE: Committing [DataNucleus Transaction, ID=Xid=
> //-----------------------------------------------------------------
> // this is the entry object debugger showing the dirty fields...
> this    SaveTextEntryHandler  (id=151)
> action  SaveTextEntry  (id=169)
> context AbstractDispatch$DefaultExecutionContext  (id=171)
> entryId
> "agxuaW51a3UtYWxwaGFyKwsSBURpYXJ5GAQMCxILVGV4dENoYXB0ZXIYBwwLEglUZXh0RW50cnkYFQw"
> (id=172)
> entry   TextEntry  (id=160)
>        accountId       Long  (id=174)
>        byLine  "" (id=177)
>        chapter TextChapter  (id=178)
>        commentEntrys   TreeSet  (id=181)
>
> id
>  
> "agxuaW51a3UtYWxwaGFyKwsSBURpYXJ5GAQMCxILVGV4dENoYXB0ZXIYBwwLEglUZXh0RW50cnkYFQw"
> (id=183)
>        jdoFlags        1
>        jdoStateManager JDOStateManagerImpl  (id=188)
>                objectValGenerators     null
>                activity        ActivityState  (id=205)
>                associatedValuesMap     HashMap<K,V>  (id=207)
>                changingState   false
>                cmd     ClassMetaData  (id=211)
>                currFM  null
>                currFMmonitor   Object  (id=213)
>                dirty   true
>                dirtyFields      (id=216)
>                        [0]     false
>                        [1]     false
>                        [2]     false
>                        [3]     false
>                        [4]     false
>                        [5]     true
>                        [6]     true
>                        [7]     true
>                        [8]     true
>                        [9]     false
>                        [10]    false
>                        [11]    false
>                embeddedOwners  null
>                fieldsToBeUpdatedAfterObjectInsertion   null
>                flushedNew      false
>                insertionNotifyList     null
>                jdoDfgFlags     1
>                loadedFields     (id=218)
>                loadingFieldsInFetchPlan        false
>                myFP    FetchPlan$FetchPlanForClass  (id=219)
>                myID    StringIdentity  (id=221)
>                myInternalID    null
>                myLC    PersistentNontransactionalDirty  (id=224)
>                myOM    ObjectManagerImpl  (id=227)
>                myPC    TextEntry  (id=160)
>                myVersion       null
>                operationalFlags        0
>                pcObjectType    0
>                postLoadPending false
>                preDeleteLoadedFields   null
>                referencedPC    null
>                relationManager null
>                restoreValues   false
>                savedFlags      1
>                savedImage      TextEntry  (id=231)
>                savedLoadedFields        (id=232)
>                storingPC       false
>                transactionalVersion    null
>                updatingForPostInsert   false
>        longContentSize Long  (id=192)
>        longContentString       "this is a long content update" (id=173)
>        privateComment  true
>        shortContent    "this is a short content update" (id=168)
>        source  SourceType  (id=200)
>        sourceId        "1259536113144" (id=203)
>        timestamp       Long  (id=204)
>
> --
>
> You received this message because you are subscribed to the Google Groups
> "Google App Engine for Java" group.
> To post to this group, send email to
> google-appengine-j...@googlegroups.com.
> To unsubscribe from this group, send email to
> google-appengine-java+unsubscr...@googlegroups.com<google-appengine-java%2bunsubscr...@googlegroups.com>
> .
> For more options, visit this group at
> http://groups.google.com/group/google-appengine-java?hl=en.
>
>
>

--

You received this message because you are subscribed to the Google Groups 
"Google App Engine for Java" group.
To post to this group, send email to google-appengine-j...@googlegroups.com.
To unsubscribe from this group, send email to 
google-appengine-java+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/google-appengine-java?hl=en.


Reply via email to