The discussion of the spec was interesting, but does anyone have any feedback or comments on my actual question?

-Gus

Gus Heck wrote:

Well I have discovered that my feeling that casting to PersistenceCapable was wrong is correct.

From page 60 of the jdo spec, regarding PersistenceCapable

NOTE: This interface is not intended to be used by application programmers.
It is for use only by implementations. Applications should use the methods
defined in class JDOHelper instead of these methods.


So rather than cast, I should use JDOHelper.getPersistenceManager(Object).

But this leaves me wondering about the usage of the JDO API... I think what I am doing probably only works because I am using very simple single objects for prototyping at the moment. JDO suddenly looks somewhat less efficient. I would appreciate comments on what I think I have deduced (follows):

It seems that JDO expects one not to hang onto references to persistant objects as I have been doing. I have come to this conclusion for the following reasons:

1. Persistent objects Must have a Persistence Manager at all times. The only way to disassociate a PO from it's PM appears to be making it transient, if otherin memory persistent objects reference the object this is a bad idea because (According to _Core Java Data Objects_ (S. Tyagi et. al) ) they will treat the transient object as a new persistent object (and I am guessing then, probably try to duplicate it in the datastore).

2. Since multiple threads (as in browser accesses) may access the datastore via JDO, it is quite possible for objectA (type=SomeClass) to be associated with PersistenceManager 1 (PM1) and objectB (type=SomeClass) to be associated with a different PM (PM2). So what happens when you later get an extent for SomeClass? I am fairly certain that this will produce a JDOUserException because objects A and B already have different persistence managers, and whichever PM you use to get them, will be unable to manage a transaction involving both objectA and objectB.

3 I suspect that this is also a problem when an instance of SomeOtherPCClass that refers to a collection containing objectA and objectB tries to commit itself, and the collection is marked dirty....

So with all that in mind it seems that one can only hold an object ID, not a reference to an Object, and the pattern for access (keeping the rest of the application unaware of JDO) would look something like this:

Object storedOID;

SomeObject getFoo(){
PersistenceManager pm = pmf.getPersistenceManager();
SomeObject temp = pm.getObjectById(storedOID);
Transaction tx = pm.currentTransaction();
tx.begin();
String foo = temp.getFoo()
tx.commit(); // or rollback
pm.close();
return foo;
} // temp goes out of scope and is GC'd and pm also should get GC'd along wiht tx


This is somewhat longer and creates more GC than my previous, pattern (before the workaround):

SomeObject someObjectInstance;

SomeObject getFoo() {
PersistenceManager pm = pmf.getPersistenceManager();
Transaction tx = pm.currentTransaction();
tx.begin();
String foo = someObjectInstance.getFoo()
tx.commit(); // or rollback
return foo;
} // only tx would get GC'd because pc classes hold a reference to their PM


However, I am not sure what happens when you getObjectById and it is already in use somewhere else.... the spec/api doesn't seem to address that. Does it block or throw an exception? I would expect it blocks since there is no exception declared... Comments?

-Gus

Mahler Thomas wrote:

Hi Gus,

I think all works as designed here. you have some persistent object "data"
that was persisted at some time before calling the prepareTX method.


being a PersistenceCapable Object data still has its old PersistenceManager.
If you use a new PM to open a transaction, data is still connected to its
original PM which has no open transaction.
That's why you get the Exception "javax.jdo.JDOUserException: Transaction is
not active.".


So IMO you solution to use the original PM is not a "workaround", but just
the right thing to do!


cheers,
Thomas



-----Original Message-----
From: Gus Heck [mailto:[EMAIL PROTECTED]
Sent: Monday, December 08, 2003 7:50 PM
To: OJB Users List
Subject: Re: JDO Bug (status please)


Yes I seem to have confirmed that it is a problem with getting the wrong Persistence Manager. I changed PrepareTX() to look like this:


private TXData prepareTX() {
TXData td = new TXData();
td.pm = ((javax.jdo.spi.PersistenceCapable)data).jdoGetPersistenceManager();
if (td.pm == null) {
td.pm = PersistenceHelper.getPMF().getPersistenceManager();
}
td.tx = td.pm.currentTransaction();
//System.out.println("1 tx.isAcitve():"+td.tx.isActive());
td.tx.begin();
//System.out.println("2 tx.isAcitve():"+td.tx.isActive());
return td;
}
and I get this output:


3 tx.isActive():true
PM for tx:[EMAIL PROTECTED]
PM for data:[EMAIL PROTECTED]

And the database is successfully updated. So now there is a workaround, which is a huge improvement, but casting to PersistenceCapable shouldn't be needed...

-Gus

Gus Heck wrote:





--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]




--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]



Reply via email to