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 [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/google-appengine-java?hl=en.


Reply via email to