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.