Re: JDO Usage patterns? [was Re: JDO Bug (status please)]
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
Re: JDO Usage patterns? [was Re: JDO Bug (status please)]
I call the requirement that any persistent class implement PersistenceCapable an evil part of the spec for the SPI as it is completely unnecessary. If a vendor chooses to use bytecode enhancement/generation/etc they are welcome to, but to require it as part of the spec is just annoying and encourages bad practices. Anything obtainable from the PC interface is obtainable via the helper class, and that lets the behind-the-curtain stuff remain behind the curtain. Requiring the ability to cast to PC is a hack, and a hack in a spec not an implementation, which is worse. -Brian On Dec 9, 2003, at 2:45 PM, Gus Heck wrote: The reason I expected to be wrong was that PC is listed as part of the SPI not the API. If applications muck around in the SPI then they may get information that is inconsistant with the same information provided by the API. The JDO vendor (OJB) may be doing fancy (and maybe even cool and useful) stuff you arn't supposed to see before giving it to you through the api, but accessing it through the SPI may short circuit the vendor's code. That is the theory as I understand it at least. Why is that evil? - Gus Brian McCallister wrote: On Dec 9, 2003, at 2:04 PM, Gus Heck wrote: Well I have discovered that my feeling that casting to PersistenceCapable was wrong is correct. I prefer the term "evil" for this part of the spec ;-) (sorry Matt) -Brian - 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] - To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
Re: JDO Usage patterns? [was Re: JDO Bug (status please)]
The reason I expected to be wrong was that PC is listed as part of the SPI not the API. If applications muck around in the SPI then they may get information that is inconsistant with the same information provided by the API. The JDO vendor (OJB) may be doing fancy (and maybe even cool and useful) stuff you arn't supposed to see before giving it to you through the api, but accessing it through the SPI may short circuit the vendor's code. That is the theory as I understand it at least. Why is that evil? - Gus Brian McCallister wrote: On Dec 9, 2003, at 2:04 PM, Gus Heck wrote: Well I have discovered that my feeling that casting to PersistenceCapable was wrong is correct. I prefer the term "evil" for this part of the spec ;-) (sorry Matt) -Brian - 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]
Re: JDO Usage patterns? [was Re: JDO Bug (status please)]
On Dec 9, 2003, at 2:04 PM, Gus Heck wrote: Well I have discovered that my feeling that casting to PersistenceCapable was wrong is correct. I prefer the term "evil" for this part of the spec ;-) (sorry Matt) -Brian - To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
JDO Usage patterns? [was Re: JDO Bug (status please)]
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 upda
RE: JDO Bug (status please)
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: > > > Hi, > > > > First of all, Thanks! :) I have pluged it into my code and I am > > getting getting further, but then I get an error. I don't > know if it > > is my fault or a bug, though. Here is what I am doing: > > > > I have a class that wraps my persistant object and handles > all the JDO > > stuff so that the rest of the program doesn't have to know anything > > about JDO. It has these methods (among others) > > > >private TXData prepareTX() { > >TXData td = new TXData(); > >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; > >} > > private void commitTX(TXData td) { > >td.tx.commit(); > >// I used to do td.pm.close() but that seemed to > >// give me errors saying PM was closed. > >} > > public void setCity(String city) { > >if (JDOHelper.isPersistent(this.data)) { > >TXData td = prepareTX(); > >System.out.println("3 tx.isActive():"+td.tx.isActive()); > >System.out.println("PM for > > tx:"+td.tx.getPersistenceManager()); > >System.out.println("PM for > > > data:"+((javax.jdo.spi.PersistenceCapable)data).jdoGetPersiste > nceManager()); > > > >data.setCity(city); > >commitTX(td); > >} else { > >data.setCity(city); > >} > >} > > > > I am getting this errror: > > > > at > > > org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run( > ThreadPool.java:619) > > > > at java.lang.Thread.run(Thread.java:534) > > Caused by: javax.jdo.JDOUserException: Transaction is not active. > > at > > com.sun.jdori.common.state.LifeCycleState.assertTransaction(Unknown > > Source) > > at > > > com.sun.jdori.common.state.PersistentNonTransactional.transiti > onWriteField(Unknown > > Source) > > at > > > com.sun.jdori.common.state.StateManagerImpl.prepareSetField2(Unknown > > Source) > > at > > com.sun.jdori.common.state.StateManagerImpl.prepareSetField(Unknown > > Source) > > at > > com.sun.jdori.common.state.StateManagerImpl.setStringField(Unknown > > Source) > > at > org.cs101.fdb.impl.jdo.LocationBase.jdoSetcity(LocationBase.java) > > at > org.cs101.fdb.impl.jdo.LocationBase.setCity(LocationBase.java:122) > > at > org.cs101.fdb.impl.jdo.LocationImpl.setCity(LocationImpl.java:287) >
Re: JDO Bug (status please)
at one gets a handle on the results of an extent call was the constructor for OJBExtent. (please tell me if there is an earlier/better point to get to the results) That's exactly the correct attack point. The patch I had in mind does exactly what you have done: looping through all loaded instances an assigning the SM. I tried hacking the Constructor to look like this just to see if it fixed the problem: private Iterator iterator; private Class clazz; private PersistenceBroker broker; /** * Constructor for OjbExtent. */ public OjbExtent(Class pClazz, PersistenceBroker pBroker) { clazz = pClazz; System.out.println(pBroker.getClass()); Criteria selectExtent = null; Query q = QueryFactory.newQuery(clazz, selectExtent); broker = pBroker; RsIterator iter = (RsIterator) broker.getIteratorByQuery(q); // cycle through the extent and give the objects a statemanager ArrayList temp = new ArrayList(); while (iter.hasNext()) { Object o = iter.next(); Identity oid = new Identity(o, broker); PersistenceCapable pc; // theoretically this should never happen, but... if (o instanceof PersistenceCapable) { pc = (PersistenceCapable) o; } else { throw new RuntimeException("OJBExents are returning classes " + "that are not javax.jdo.spi.PersistenceCapapble??"); } // FIXME: // Something of a Hack... The current implementation of JDO in OJB // guarantees that this cast works, but I don't think it is // in any way guaranteed not to change. PersistenceManagerImpl pm = (PersistenceManagerImpl) pc.jdoGetPersistenceManager(); StateManagerInternal sm = pm.findStateManager(pc); pc.jdoReplaceStateManager(sm); temp.add(pc); } iter.releaseDbResources(); this.iterator = temp.iterator(); } I never got to see if this had an effect though because it caused a very surprising NPE... pc.jdoGetPersistenceManager() is returning null. So not only do the objects not have a state manager, they don't have a persistence manager! The objects are just loaded by the PB, so they have no PM yet. Any clue how to address this?? I don't see any way to generate and supply a PersistenceManager for the object. Not really. As there is no documentation about the JDORI internals available the only solution is to study the code of the JDORI default FOStore solution. I have a feeling that there is some other place I should be looking I feel like I don't yet understand how the sun RI gets diverted/configured into using the OJB backend That seems like another possible point of attack but I havn't found it yet. I believe the point of attack is OK. we simply have to find a way obtain the needed hooks into the JDORI. this can be a real pita. But it will work in the end :-) (can you imagine what a hard job it was to write the whole plugin? It took me long, long days of debugging through the JDORI. But in the end the coding itself took only a few hours.) I will review your patch this weekend. So I hope we get you started by next week! thanks for your patience and also for sharing your patch! - thomas -Gus Mahler Thomas wrote: Hi Gus, Yes, I hope to get my hands on the open JDO issues very soon! Thomas -----Original Message- From: Gus Heck [mailto:[EMAIL PROTECTED] Sent: Tuesday, December 02, 2003 7:59 PM To: OJB Users List Subject: Re: JDO Bug (status please) I just got bit by this, despite the fact I had read this thread. I forgot and coded a method that asked if an object is persistant, and if not caused it to get a new ID and make itself persistant. I noticed something interesting though I edited and changed an object, then inadvertently created a copy of it because of the ID aquisition issue I just described, but when I did another extent to display a list of all items, both the old object and the inadvertently created object were identical right down to the ID. Logging intto mysql and doing a select shows that this is not what has happened in the DB. So it looks like the transient objects returned by the extent are still cached objects and may become modified without effecting the database. This means that data can appear to be written to the database but in fact is not! I hope you will have time to work on this very soon, I'm digging through the discussion referenced below and having trouble picking out what exactly the work around is... If you or someone else could post a direct workaround for getting a list of all objects of a class that are persistant it would help a lot. TIA, Gus Mahler Thomas wrote: -
Re: JDO Bug (status please)
// cycle through the extent and give the objects a statemanager ArrayList temp = new ArrayList(); while (iter.hasNext()) { Object o = iter.next(); Identity oid = new Identity(o, broker); PersistenceCapable pc; // theoretically this should never happen, but... if (o instanceof PersistenceCapable) { pc = (PersistenceCapable) o; } else { throw new RuntimeException("OJBExents are returning classes " + "that are not javax.jdo.spi.PersistenceCapapble??"); } // FIXME: // Something of a Hack... The current implementation of JDO in OJB // guarantees that this cast works, but I don't think it is // in any way guaranteed not to change. PersistenceManagerImpl pm = (PersistenceManagerImpl) pc.jdoGetPersistenceManager(); StateManagerInternal sm = pm.findStateManager(pc); pc.jdoReplaceStateManager(sm); temp.add(pc); } iter.releaseDbResources(); this.iterator = temp.iterator(); } I never got to see if this had an effect though because it caused a very surprising NPE... pc.jdoGetPersistenceManager() is returning null. So not only do the objects not have a state manager, they don't have a persistence manager! The objects are just loaded by the PB, so they have no PM yet. Any clue how to address this?? I don't see any way to generate and supply a PersistenceManager for the object. Not really. As there is no documentation about the JDORI internals available the only solution is to study the code of the JDORI default FOStore solution. I have a feeling that there is some other place I should be looking I feel like I don't yet understand how the sun RI gets diverted/configured into using the OJB backend That seems like another possible point of attack but I havn't found it yet. I believe the point of attack is OK. we simply have to find a way obtain the needed hooks into the JDORI. this can be a real pita. But it will work in the end :-) (can you imagine what a hard job it was to write the whole plugin? It took me long, long days of debugging through the JDORI. But in the end the coding itself took only a few hours.) I will review your patch this weekend. So I hope we get you started by next week! thanks for your patience and also for sharing your patch! - thomas -Gus Mahler Thomas wrote: Hi Gus, Yes, I hope to get my hands on the open JDO issues very soon! Thomas -Original Message- From: Gus Heck [mailto:[EMAIL PROTECTED] Sent: Tuesday, December 02, 2003 7:59 PM To: OJB Users List Subject: Re: JDO Bug (status please) I just got bit by this, despite the fact I had read this thread. I forgot and coded a method that asked if an object is persistant, and if not caused it to get a new ID and make itself persistant. I noticed something interesting though I edited and changed an object, then inadvertently created a copy of it because of the ID aquisition issue I just described, but when I did another extent to display a list of all items, both the old object and the inadvertently created object were identical right down to the ID. Logging intto mysql and doing a select shows that this is not what has happened in the DB. So it looks like the transient objects returned by the extent are still cached objects and may become modified without effecting the database. This means that data can appear to be written to the database but in fact is not! I hope you will have time to work on this very soon, I'm digging through the discussion referenced below and having trouble picking out what exactly the work around is... If you or someone else could post a direct workaround for getting a list of all objects of a class that are persistant it would help a lot. TIA, Gus Mahler Thomas 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] - 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]
Re: JDO Bug (status please)
Hi all, Good news! Thanks to Gus getting me started. I've fixed this pita bug at last! it's in CVS HEAD already. cu, thomas Thomas Mahler wrote: Hi Gus, Gus Heck wrote: Well, since I am relatively stuck I peeked under the hood and took a stab at fixing this, based on the assumption that the analysis in the previous news group discussion of a missing state manger is the problem. thanks for helping! Yes I guess the missing state managers are the problem. After some thinking and lots of tracking back and forth through OJB persistence broker stuff and being generally confused :-) I realized that the problem can't really be there... That part is also used by non-jdo implementations, and JDO specific stuff must reside in the o.a.o.jdori.sql classes. (duh, silly me) To do anything involving a state manager outside of that package would make ojb's persistence broker depend on the sun reference implementation of JDO. (I suspect that is unacceptable ;) ). You are absolutely right. the problem must be fixed inside the jdori package. I figure that we want to get the state manager set as early as possible because it may be needed by any class that handles the PC objects generated in the extent. So the first place I could find that one gets a handle on the results of an extent call was the constructor for OJBExtent. (please tell me if there is an earlier/better point to get to the results) That's exactly the correct attack point. The patch I had in mind does exactly what you have done: looping through all loaded instances an assigning the SM. I tried hacking the Constructor to look like this just to see if it fixed the problem: private Iterator iterator; private Class clazz; private PersistenceBroker broker; /** * Constructor for OjbExtent. */ public OjbExtent(Class pClazz, PersistenceBroker pBroker) { clazz = pClazz; System.out.println(pBroker.getClass()); Criteria selectExtent = null; Query q = QueryFactory.newQuery(clazz, selectExtent); broker = pBroker; RsIterator iter = (RsIterator) broker.getIteratorByQuery(q); // cycle through the extent and give the objects a statemanager ArrayList temp = new ArrayList(); while (iter.hasNext()) { Object o = iter.next(); Identity oid = new Identity(o, broker); PersistenceCapable pc; // theoretically this should never happen, but... if (o instanceof PersistenceCapable) { pc = (PersistenceCapable) o; } else { throw new RuntimeException("OJBExents are returning classes " + "that are not javax.jdo.spi.PersistenceCapapble??"); } // FIXME: // Something of a Hack... The current implementation of JDO in OJB // guarantees that this cast works, but I don't think it is // in any way guaranteed not to change. PersistenceManagerImpl pm = (PersistenceManagerImpl) pc.jdoGetPersistenceManager(); StateManagerInternal sm = pm.findStateManager(pc); pc.jdoReplaceStateManager(sm); temp.add(pc); } iter.releaseDbResources(); this.iterator = temp.iterator(); } I never got to see if this had an effect though because it caused a very surprising NPE... pc.jdoGetPersistenceManager() is returning null. So not only do the objects not have a state manager, they don't have a persistence manager! The objects are just loaded by the PB, so they have no PM yet. Any clue how to address this?? I don't see any way to generate and supply a PersistenceManager for the object. Not really. As there is no documentation about the JDORI internals available the only solution is to study the code of the JDORI default FOStore solution. I have a feeling that there is some other place I should be looking I feel like I don't yet understand how the sun RI gets diverted/configured into using the OJB backend That seems like another possible point of attack but I havn't found it yet. I believe the point of attack is OK. we simply have to find a way obtain the needed hooks into the JDORI. this can be a real pita. But it will work in the end :-) (can you imagine what a hard job it was to write the whole plugin? It took me long, long days of debugging through the JDORI. But in the end the coding itself took only a few hours.) I will review your patch this weekend. So I hope we get you started by next week! thanks for your patience and also for sharing your patch! - thomas -Gus Mahler Thomas wrote: Hi Gus, Yes, I hope to get my hands on the open JDO issues very soon! Thomas -Original Message- From: Gus Heck [mailto:[EMAIL PROTECTED] Sent: Tuesday, December 02, 2003 7:59 PM To: OJB Users List Subject: Re: JDO Bug (s
Re: JDO Bug (status please)
Hi Gus, Gus Heck wrote: Well, since I am relatively stuck I peeked under the hood and took a stab at fixing this, based on the assumption that the analysis in the previous news group discussion of a missing state manger is the problem. thanks for helping! Yes I guess the missing state managers are the problem. After some thinking and lots of tracking back and forth through OJB persistence broker stuff and being generally confused :-) I realized that the problem can't really be there... That part is also used by non-jdo implementations, and JDO specific stuff must reside in the o.a.o.jdori.sql classes. (duh, silly me) To do anything involving a state manager outside of that package would make ojb's persistence broker depend on the sun reference implementation of JDO. (I suspect that is unacceptable ;) ). You are absolutely right. the problem must be fixed inside the jdori package. I figure that we want to get the state manager set as early as possible because it may be needed by any class that handles the PC objects generated in the extent. So the first place I could find that one gets a handle on the results of an extent call was the constructor for OJBExtent. (please tell me if there is an earlier/better point to get to the results) That's exactly the correct attack point. The patch I had in mind does exactly what you have done: looping through all loaded instances an assigning the SM. I tried hacking the Constructor to look like this just to see if it fixed the problem: private Iterator iterator; private Class clazz; private PersistenceBroker broker; /** * Constructor for OjbExtent. */ public OjbExtent(Class pClazz, PersistenceBroker pBroker) { clazz = pClazz; System.out.println(pBroker.getClass()); Criteria selectExtent = null; Query q = QueryFactory.newQuery(clazz, selectExtent); broker = pBroker; RsIterator iter = (RsIterator) broker.getIteratorByQuery(q); // cycle through the extent and give the objects a statemanager ArrayList temp = new ArrayList(); while (iter.hasNext()) { Object o = iter.next(); Identity oid = new Identity(o, broker); PersistenceCapable pc; // theoretically this should never happen, but... if (o instanceof PersistenceCapable) { pc = (PersistenceCapable) o; } else { throw new RuntimeException("OJBExents are returning classes " + "that are not javax.jdo.spi.PersistenceCapapble??"); } // FIXME: // Something of a Hack... The current implementation of JDO in OJB // guarantees that this cast works, but I don't think it is // in any way guaranteed not to change. PersistenceManagerImpl pm = (PersistenceManagerImpl) pc.jdoGetPersistenceManager(); StateManagerInternal sm = pm.findStateManager(pc); pc.jdoReplaceStateManager(sm); temp.add(pc); } iter.releaseDbResources(); this.iterator = temp.iterator(); } I never got to see if this had an effect though because it caused a very surprising NPE... pc.jdoGetPersistenceManager() is returning null. So not only do the objects not have a state manager, they don't have a persistence manager! The objects are just loaded by the PB, so they have no PM yet. Any clue how to address this?? I don't see any way to generate and supply a PersistenceManager for the object. Not really. As there is no documentation about the JDORI internals available the only solution is to study the code of the JDORI default FOStore solution. I have a feeling that there is some other place I should be looking I feel like I don't yet understand how the sun RI gets diverted/configured into using the OJB backend That seems like another possible point of attack but I havn't found it yet. I believe the point of attack is OK. we simply have to find a way obtain the needed hooks into the JDORI. this can be a real pita. But it will work in the end :-) (can you imagine what a hard job it was to write the whole plugin? It took me long, long days of debugging through the JDORI. But in the end the coding itself took only a few hours.) I will review your patch this weekend. So I hope we get you started by next week! thanks for your patience and also for sharing your patch! - thomas -Gus Mahler Thomas wrote: Hi Gus, Yes, I hope to get my hands on the open JDO issues very soon! Thomas -Original Message- From: Gus Heck [mailto:[EMAIL PROTECTED] Sent: Tuesday, December 02, 2003 7:59 PM To: OJB Users List Subject: Re: JDO Bug (status please) I just got bit by this, despite the fact I had read this thread. I forgot and coded a method that asked if an object is persistant, and if not caused it to g
Re: JDO Bug (status please)
Well, since I am relatively stuck I peeked under the hood and took a stab at fixing this, based on the assumption that the analysis in the previous news group discussion of a missing state manger is the problem. After some thinking and lots of tracking back and forth through OJB persistence broker stuff and being generally confused I realized that the problem can't really be there... That part is also used by non-jdo implementations, and JDO specific stuff must reside in the o.a.o.jdori.sql classes. (duh, silly me) To do anything involving a state manager outside of that package would make ojb's persistence broker depend on the sun reference implementation of JDO. (I suspect that is unacceptable ;) ). I figure that we want to get the state manager set as early as possible because it may be needed by any class that handles the PC objects generated in the extent. So the first place I could find that one gets a handle on the results of an extent call was the constructor for OJBExtent. (please tell me if there is an earlier/better point to get to the results) I tried hacking the Constructor to look like this just to see if it fixed the problem: private Iterator iterator; private Class clazz; private PersistenceBroker broker; /** * Constructor for OjbExtent. */ public OjbExtent(Class pClazz, PersistenceBroker pBroker) { clazz = pClazz; System.out.println(pBroker.getClass()); Criteria selectExtent = null; Query q = QueryFactory.newQuery(clazz, selectExtent); broker = pBroker; RsIterator iter = (RsIterator) broker.getIteratorByQuery(q); // cycle through the extent and give the objects a statemanager ArrayList temp = new ArrayList(); while (iter.hasNext()) { Object o = iter.next(); Identity oid = new Identity(o, broker); PersistenceCapable pc; // theoretically this should never happen, but... if (o instanceof PersistenceCapable) { pc = (PersistenceCapable) o; } else { throw new RuntimeException("OJBExents are returning classes " + "that are not javax.jdo.spi.PersistenceCapapble??"); } // FIXME: // Something of a Hack... The current implementation of JDO in OJB // guarantees that this cast works, but I don't think it is // in any way guaranteed not to change. PersistenceManagerImpl pm = (PersistenceManagerImpl) pc.jdoGetPersistenceManager(); StateManagerInternal sm = pm.findStateManager(pc); pc.jdoReplaceStateManager(sm); temp.add(pc); } iter.releaseDbResources(); this.iterator = temp.iterator(); } I never got to see if this had an effect though because it caused a very surprising NPE... pc.jdoGetPersistenceManager() is returning null. So not only do the objects not have a state manager, they don't have a persistence manager! Any clue how to address this?? I don't see any way to generate and supply a PersistenceManager for the object. I have a feeling that there is some other place I should be looking I feel like I don't yet understand how the sun RI gets diverted/configured into using the OJB backend That seems like another possible point of attack but I havn't found it yet. -Gus Mahler Thomas wrote: Hi Gus, Yes, I hope to get my hands on the open JDO issues very soon! Thomas -Original Message- From: Gus Heck [mailto:[EMAIL PROTECTED] Sent: Tuesday, December 02, 2003 7:59 PM To: OJB Users List Subject: Re: JDO Bug (status please) I just got bit by this, despite the fact I had read this thread. I forgot and coded a method that asked if an object is persistant, and if not caused it to get a new ID and make itself persistant. I noticed something interesting though I edited and changed an object, then inadvertently created a copy of it because of the ID aquisition issue I just described, but when I did another extent to display a list of all items, both the old object and the inadvertently created object were identical right down to the ID. Logging intto mysql and doing a select shows that this is not what has happened in the DB. So it looks like the transient objects returned by the extent are still cached objects and may become modified without effecting the database. This means that data can appear to be written to the database but in fact is not! I hope you will have time to work on this very soon, I'm digging through the discussion referenced below and having trouble picking out what exactly the work around is... If you or someone else could post a direct workaround for getting a list of all objects of a class that are persistant it would help a lot. TIA, Gus Mahler Thomas wrote:
RE: JDO Bug (status please)
Hi Gus, Yes, I hope to get my hands on the open JDO issues very soon! Thomas > -Original Message- > From: Gus Heck [mailto:[EMAIL PROTECTED] > Sent: Tuesday, December 02, 2003 7:59 PM > To: OJB Users List > Subject: Re: JDO Bug (status please) > > > I just got bit by this, despite the fact I had read this thread. I > forgot and coded a method that asked if an object is > persistant, and if > not caused it to get a new ID and make itself persistant. > > I noticed something interesting though I edited and changed an > object, then inadvertently created a copy of it because of the ID > aquisition issue I just described, but when I did another extent to > display a list of all items, both the old object and the > inadvertently > created object were identical right down to the ID. Logging > intto mysql > and doing a select shows that this is not what has happened > in the DB. > So it looks like the transient objects returned by the extent > are still > cached objects and may become modified without effecting the database. > > This means that data can appear to be written to the database but in > fact is not! > > I hope you will have time to work on this very soon, I'm > digging through > the discussion referenced below and having trouble picking out what > exactly the work around is... If you or someone else could post a > direct workaround for getting a list of all objects of a > class that are > persistant it would help a lot. > > TIA, > Gus > > Mahler Thomas wrote: > > >Hi Nick, > > > > > > > > > >>Hi- > >> > >>An earlier thread on this list: > >>http://www.mail-archive.com/[EMAIL PROTECTED]/msg03832.html > >>describes a _serious_ bug in the JDO interface to OJB. > >> > >>I posted about this last week and haven't gotten a response > yet. I'm > >>really hoping that someone can shed some light on the status of this > >>issue, otherwise it just doesn't make sense to use the JDO > API at all. > >> > >> > > > >This bug is still open. (Lazy me) > >I've started to work on the issue, but did not get very far yet. > >As I'm currently very busy I can't make any promises when it > will be fixed. > > > >cheers, > >Thomas > > > > > > > > > >>Thanks, > >>Nick > >> > >> > >> > >>-Forwarded Message- > >> > >>From: Nick Ohanian <[EMAIL PROTECTED]> > >>To: OJB Users List <[EMAIL PROTECTED]> > >>Subject: JDO Query/Extent Problem > >>Date: 14 Nov 2003 00:38:55 -0800 > >> > >>Hi- > >> > >>There was a thread on this list regarding the fact that when > >>using JDO, > >>Extent or Query results act transient, not persistent. That > >>is, if you > >>look up an object with a Query and edit it, those changes are not > >>persisted back to the database on commit. The only way to get a > >>"really" persistent object is to look it up by an Identity. > >> > >>Note that this is the kind of lookup used by Tutorial 4. > >>Indeed if you > >>look at the source for UCEditProduct (the actual file in > >>src/jdori/org/apache/ojb/tutorial5/UCEditProduct.java, not > >>the source on > >>the Tutorial 4 web page), you can see that the use of a Query object > >>appears to be commented out in place of the Identity object. > >> > >>The thread that I'm referring to can be found here (it > explains things > >>in some more detail): > >>http://www.mail-archive.com/[EMAIL PROTECTED]/msg03832.html > >> > >>This makes the JDO API... less than ideal. ;) > >> > >>Has this problem been addressed already? Is there a fix available? > >> > >>Thanks so much, > >>Nick > >> > >> > >> > >> > >> > >> > - > >>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] > >> > >> > >> > > > > > >- > >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] > - To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
Re: JDO Bug (status please)
I just got bit by this, despite the fact I had read this thread. I forgot and coded a method that asked if an object is persistant, and if not caused it to get a new ID and make itself persistant. I noticed something interesting though I edited and changed an object, then inadvertently created a copy of it because of the ID aquisition issue I just described, but when I did another extent to display a list of all items, both the old object and the inadvertently created object were identical right down to the ID. Logging intto mysql and doing a select shows that this is not what has happened in the DB. So it looks like the transient objects returned by the extent are still cached objects and may become modified without effecting the database. This means that data can appear to be written to the database but in fact is not! I hope you will have time to work on this very soon, I'm digging through the discussion referenced below and having trouble picking out what exactly the work around is... If you or someone else could post a direct workaround for getting a list of all objects of a class that are persistant it would help a lot. TIA, Gus Mahler Thomas wrote: Hi Nick, Hi- An earlier thread on this list: http://www.mail-archive.com/[EMAIL PROTECTED]/msg03832.html describes a _serious_ bug in the JDO interface to OJB. I posted about this last week and haven't gotten a response yet. I'm really hoping that someone can shed some light on the status of this issue, otherwise it just doesn't make sense to use the JDO API at all. This bug is still open. (Lazy me) I've started to work on the issue, but did not get very far yet. As I'm currently very busy I can't make any promises when it will be fixed. cheers, Thomas Thanks, Nick -Forwarded Message- From: Nick Ohanian <[EMAIL PROTECTED]> To: OJB Users List <[EMAIL PROTECTED]> Subject: JDO Query/Extent Problem Date: 14 Nov 2003 00:38:55 -0800 Hi- There was a thread on this list regarding the fact that when using JDO, Extent or Query results act transient, not persistent. That is, if you look up an object with a Query and edit it, those changes are not persisted back to the database on commit. The only way to get a "really" persistent object is to look it up by an Identity. Note that this is the kind of lookup used by Tutorial 4. Indeed if you look at the source for UCEditProduct (the actual file in src/jdori/org/apache/ojb/tutorial5/UCEditProduct.java, not the source on the Tutorial 4 web page), you can see that the use of a Query object appears to be commented out in place of the Identity object. The thread that I'm referring to can be found here (it explains things in some more detail): http://www.mail-archive.com/[EMAIL PROTECTED]/msg03832.html This makes the JDO API... less than ideal. ;) Has this problem been addressed already? Is there a fix available? Thanks so much, Nick - 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] - 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]
RE: JDO Bug (status please)
Hi Nick, > Hi- > > An earlier thread on this list: > http://www.mail-archive.com/[EMAIL PROTECTED]/msg03832.html > describes a _serious_ bug in the JDO interface to OJB. > > I posted about this last week and haven't gotten a response yet. I'm > really hoping that someone can shed some light on the status of this > issue, otherwise it just doesn't make sense to use the JDO API at all. This bug is still open. (Lazy me) I've started to work on the issue, but did not get very far yet. As I'm currently very busy I can't make any promises when it will be fixed. cheers, Thomas > > Thanks, > Nick > > > > -Forwarded Message- > > From: Nick Ohanian <[EMAIL PROTECTED]> > To: OJB Users List <[EMAIL PROTECTED]> > Subject: JDO Query/Extent Problem > Date: 14 Nov 2003 00:38:55 -0800 > > Hi- > > There was a thread on this list regarding the fact that when > using JDO, > Extent or Query results act transient, not persistent. That > is, if you > look up an object with a Query and edit it, those changes are not > persisted back to the database on commit. The only way to get a > "really" persistent object is to look it up by an Identity. > > Note that this is the kind of lookup used by Tutorial 4. > Indeed if you > look at the source for UCEditProduct (the actual file in > src/jdori/org/apache/ojb/tutorial5/UCEditProduct.java, not > the source on > the Tutorial 4 web page), you can see that the use of a Query object > appears to be commented out in place of the Identity object. > > The thread that I'm referring to can be found here (it explains things > in some more detail): > http://www.mail-archive.com/[EMAIL PROTECTED]/msg03832.html > > This makes the JDO API... less than ideal. ;) > > Has this problem been addressed already? Is there a fix available? > > Thanks so much, > Nick > > > > > > - > 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] > - To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
JDO Bug (status please)
Hi- An earlier thread on this list: http://www.mail-archive.com/[EMAIL PROTECTED]/msg03832.html describes a _serious_ bug in the JDO interface to OJB. I posted about this last week and haven't gotten a response yet. I'm really hoping that someone can shed some light on the status of this issue, otherwise it just doesn't make sense to use the JDO API at all. Thanks, Nick -Forwarded Message- From: Nick Ohanian <[EMAIL PROTECTED]> To: OJB Users List <[EMAIL PROTECTED]> Subject: JDO Query/Extent Problem Date: 14 Nov 2003 00:38:55 -0800 Hi- There was a thread on this list regarding the fact that when using JDO, Extent or Query results act transient, not persistent. That is, if you look up an object with a Query and edit it, those changes are not persisted back to the database on commit. The only way to get a "really" persistent object is to look it up by an Identity. Note that this is the kind of lookup used by Tutorial 4. Indeed if you look at the source for UCEditProduct (the actual file in src/jdori/org/apache/ojb/tutorial5/UCEditProduct.java, not the source on the Tutorial 4 web page), you can see that the use of a Query object appears to be commented out in place of the Identity object. The thread that I'm referring to can be found here (it explains things in some more detail): http://www.mail-archive.com/[EMAIL PROTECTED]/msg03832.html This makes the JDO API... less than ideal. ;) Has this problem been addressed already? Is there a fix available? Thanks so much, Nick - 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]