August Detlefsen wrote:
I recently ran into this and I'm interested to know if it is
designed-in behavior, a bug, or a 'feature'. The abstract is that I
needed to create a NavPageContent Object, then use its ID to formulate
a link String, which was then set back into the same Object and
persisted.


When I tried something like this:

db.create(page);
String link = "/page/" + page.getId();
page.setLink(link);
db.commit();

I get this error:

org.exolab.castor.jdo.ObjectModifiedException: Transaction aborted:
Object of type model.NavPageContent with identity 6,044 has been
modified by a concurrent transaction (cache entry is different from
database row)
        at
org.exolab.castor.jdo.engine.SQLEngine.store(SQLEngine.java:882)
        at
org.exolab.castor.persist.ClassMolder.store(ClassMolder.java:1609)
        at
org.exolab.castor.persist.LockEngine.store(LockEngine.java:750)
        at
org.exolab.castor.persist.TransactionContext.prepare(TransactionContext.java:1540)
        at
org.exolab.castor.jdo.engine.DatabaseImpl.commit(DatabaseImpl.java:512)
        at AdminController.dispatchPage(AdminController.java:1087)
        at AdminController.service(AdminController.java:157)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:853)
        at
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:247)
....


Ultimately as a workaround I had to create the object, commit, expire the cache, close the DB, reopen the DB, reload the object, make the changes and commit:

db.create(page);
db.commit();
//expire cache
Class[] type      = { NavPageContent.class } ;
Object[] identity = { page.getId() } ;
db.expireCache( type, identity );

db.close();
db = jdo.getDatabase();
db.begin();
page = (NavPageContent)db.load(NavPageContent.class, page.getId());

link = "/page/" + page.getId();
page.setLink( link );

db.commit();

Is this behavior by design? Is there some way to get the next ID rather
than actually creating the Object -Can it be pulled directly from a
sequence generator prior to create()?

August,


The ObjectModifiedException is defintely by design. In fact, it's one of Castor's biggest hidden features - dirty checking. Dirty checking is hugely powerful because it allows many tx contexts to work with the same object without stomping on one another.

First of all, what cache-type are you using for this object in the mapping descriptor? You'll need to use something other than none. The count-limited cache is the default cache-type.

The example code above is actually circumventing the dirty checking functionality completely and rendering Castor almost useless because it's a brute force approach that doesn't take into consideration the possibility of concurrency. By expiring the cache in the code example above, there is potential for overwriting someone else's changes and corrupting the data.

Because you're already using long transactions, maybe a better thing to do is to grab the timestamp from the object in the first tx using jdoGetTimeStamp() and cache it. Then in the tx where the object will be persisted just apply that timestamp to the object using jdoSetTimeStamp() before calling db.update(). This will get you around the ObjectModifiedException. The problem with this workaround is that it could get messy with concurrency.

Bruce
--
perl -e 'print unpack("u30","<0G)[EMAIL PROTECTED]&5R\"F9E<G)E=\$\!F<FEI+F-O;0\`\`");'


The Castor Project
http://www.castor.org/

Apache Geronimo
http://incubator.apache.org/projects/geronimo.html

----------------------------------------------------------- If you wish to unsubscribe from this mailing, send mail to
[EMAIL PROTECTED] with a subject of:
unsubscribe castor-dev




Reply via email to