I understand the need for dirty checking to manage concurrency across
many transactions, but what is the need for dirty checking within the
bounds of one transaction? 

In my case, I originally attempted to create the object, get the newly
created ID, us the ID to set a field within the same object, then
commit -all in the course of a single short transaction. The
ObjectModifiedException cannot be from another transaction trying to
modify the same object because in this case the create() call has not
even committed yet so there is no way for another transaction to even
know it exists. 

You are right about the second code example, it is pure hack! But it
was the only way I could get around that exception. I would love to do
it the  right way, believe me. Is this is actually a bug then?

-August





--- Bruce Snyder <[EMAIL PROTECTED]> wrote:
> 
> 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
> 


__________________________________
Do you Yahoo!?
Yahoo! Small Business $15K Web Design Giveaway 
http://promotions.yahoo.com/design_giveaway/

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

Reply via email to