castor

PersistenceException thrown loading object with some (but not all) lazy loaded fields loaded in txn

Details

  • Type: Bug Bug
  • Status: Closed Closed
  • Priority: Major Major
  • Resolution: Fixed
  • Affects Version/s: 1.0 M1, 1.0 M2, 1.0 M3
  • Fix Version/s: 1.0.1
  • Component/s: JDO lazy loading
  • Labels:
    None
  • Environment:
    jdk 1.5.0_04, mysql 4.1.16-nt, mysql Driver Version: mysql-connector-java-3.0.17-ga
  • Number of attachments :
    4

Description

I'm using castor-1.0M3 and am getting a PersistenceException (Object X links to another object, Y not loaded/updated/created in this transaction) with a lazy loaded 1:1 property in a txn used to query the primary object (in a read-only manner since I'm only rendering a web page, not updating the data) and load some, but not all lazy loaded properties.

Below is the gist of what I'm doing:

public class GolfCourse { private Long id; > private City city; > private Collection<GolfCourseTees> tees; > ... > }
> Mapping (abbreviated):
> <field name="city" type="City" lazy="true">
> <sql name="CITY_ID"/>
> </field>
> <field name="tees" type="GolfCourseTees" lazy="true"
> collection="collection">
> <sql many-key="COURSE_ID"/>
> </field>
>
> public class GolfCourseTees { > private Long id; > private GolfCourse course; > private String name; > ... > }
> <field name="id" type="long">
> <sql name="ID" type="bigint"/>
> </field>
> <field name="course" type="com.apex.mytracker.app.golf.GolfCourse"
> required="true" lazy="false">
> <sql name="COURSE_ID"/>
> </field>
> <field name="name" type="string" required="true">
> <sql name="TEES_NAME" type="char"/>
> </field>
>
> //start txn
> db.begin();
>
> //run query
> OQLQuery query = db.getQuery( "SELECT o FROM GolfCourse o WHERE id=$1" );
> query.bind( 5 );
> results = query.execute(AccessMode.ReadOnly);
> // Iterate over all the golf course results and load certain lazy-loaded
> properties
> while ( results.hasMore() ) {
> Collection<GolfCourseTees> tees = golfCourse.getTees();
> //loop through this nested property to force them to be loaded
> in this txn
> for (GolfCourseTees tee : tees) { > //... > }
> }
> //cleanup
> ...
> //commit
> db.commit(); //causes exception when I don't call getCity()
>
> I searched through Jira and it looks like there's some related entries,
> but I'm not sure if I'm using the tool wrong or if this is a bug.
>
> Thanks,
> Jon

  1. patch.C1355.20060410.txt
    10/Apr/06 4:06 PM
    55 kB
    Werner Guttmann
  2. patch-C1355-20060317.txt
    17/Mar/06 6:36 PM
    40 kB
    Ralf Joachim
  3. patch-C1355-20060411-01.txt
    10/Apr/06 6:04 PM
    53 kB
    Ralf Joachim

Issue Links

Activity

Hide
jonwilmoth added a comment -

Zip containing:

  • Ant build file to compile source/run JUnit tests
  • Java source files for "app" and JUnit test case
  • mysql sql script including table create statements and data inserts
  • castor config files (jdo-conf.xml, mapping.xml)
Show
jonwilmoth added a comment - Zip containing:
  • Ant build file to compile source/run JUnit tests
  • Java source files for "app" and JUnit test case
  • mysql sql script including table create statements and data inserts
  • castor config files (jdo-conf.xml, mapping.xml)
Hide
jonwilmoth added a comment -

I thought I'd mention a couple of things:
1) the nested properties are loaded from the db...the error occurs trying to commit the txn
2) even though the comments in the test case I submitted suggest otherwise, the error occurs regardless of if a call to GolfCourse.getCity() (which loads the lazy-loaded property) is made or not.

Show
jonwilmoth added a comment - I thought I'd mention a couple of things: 1) the nested properties are loaded from the db...the error occurs trying to commit the txn 2) even though the comments in the test case I submitted suggest otherwise, the error occurs regardless of if a call to GolfCourse.getCity() (which loads the lazy-loaded property) is made or not.
Hide
Werner Guttmann added a comment -

Thanks, Jon. I will try to look into this tomorrow. Next time, when submitting a bug report, please try to follow the bug submission guidelines available at

http://castor.org/how-to-submit-a-bug.html

Thanks in advance ...

Show
Werner Guttmann added a comment - Thanks, Jon. I will try to look into this tomorrow. Next time, when submitting a bug report, please try to follow the bug submission guidelines available at http://castor.org/how-to-submit-a-bug.html Thanks in advance ...
Hide
jonwilmoth added a comment -

I did read the how to page and I thought I'd followed the instructions...

  • A JUnit test case that 'showcases' your problem. (LazyLoadRelationshipTest.java)
  • Castor JDO configuration file. (jdo-conf.xml)
  • Castor JDO mapping file. (mapping.xml)
  • One or more 'entity' classes required to run your test case. (app package)
  • A SQL schema file (to help in the creation of required tables). (mysql.sql...which includes sample data)
  • A README file (with any additional information/instructions required to understand /run your test case. I didn't add this, but did provide an ant build file (build.xml) with a "run.test" target that spits out the test case failure to ".\temp-build\tests\TEST-LazyLoadRelationshipTest.txt"

If you let me know what's missing I'll add it. Plus, it'd be good to know since I do have another 1.0 Mx bug to log ... hopefully the last one

Thanks,
Jon

Show
jonwilmoth added a comment - I did read the how to page and I thought I'd followed the instructions...
  • A JUnit test case that 'showcases' your problem. (LazyLoadRelationshipTest.java)
  • Castor JDO configuration file. (jdo-conf.xml)
  • Castor JDO mapping file. (mapping.xml)
  • One or more 'entity' classes required to run your test case. (app package)
  • A SQL schema file (to help in the creation of required tables). (mysql.sql...which includes sample data)
  • A README file (with any additional information/instructions required to understand /run your test case. I didn't add this, but did provide an ant build file (build.xml) with a "run.test" target that spits out the test case failure to ".\temp-build\tests\TEST-LazyLoadRelationshipTest.txt"
If you let me know what's missing I'll add it. Plus, it'd be good to know since I do have another 1.0 Mx bug to log ... hopefully the last one Thanks, Jon
Hide
Werner Guttmann added a comment -

Jon, you are right in that your archive does contain everything to execute the test. But imho, it actually contains too much ... There's actually no need to include JARS, especially if you build the patch relative to src/bugs. But no worries ...

Show
Werner Guttmann added a comment - Jon, you are right in that your archive does contain everything to execute the test. But imho, it actually contains too much ... There's actually no need to include JARS, especially if you build the patch relative to src/bugs. But no worries ...
Hide
Ralf Joachim added a comment -

That's how we like your patch to look like. Having said that I do not know yet what goes wrong here.

Show
Ralf Joachim added a comment - That's how we like your patch to look like. Having said that I do not know yet what goes wrong here.
Hide
Werner Guttmann added a comment -

Initial and final patch, making slight and necessary modifications to a few classes related to lazy loading (SingleProxy, LazyCGLIB, etc.)

Show
Werner Guttmann added a comment - Initial and final patch, making slight and necessary modifications to a few classes related to lazy loading (SingleProxy, LazyCGLIB, etc.)
Hide
Werner Guttmann added a comment -

Final patch, fixing above issue. Jon, can you please verify whether this fix makes CASTOR-1365 disppear as well ?

Show
Werner Guttmann added a comment - Final patch, fixing above issue. Jon, can you please verify whether this fix makes CASTOR-1365 disppear as well ?
Hide
Ralf Joachim added a comment -

Great work that you could manage to resolve this.

Some minor modifications to ObjectTracker and MyAppObject for you to think about. Also used 'c1355' as database name instead of '1355' as I couldn't manage to setup a database with a number only. Having asked myself if the change of lizence at LazyCGLIB back to intalio one was by intention.

I suggest to commit as is and integrate test into CTF later when we refactor other tests.

Show
Ralf Joachim added a comment - Great work that you could manage to resolve this. Some minor modifications to ObjectTracker and MyAppObject for you to think about. Also used 'c1355' as database name instead of '1355' as I couldn't manage to setup a database with a number only. Having asked myself if the change of lizence at LazyCGLIB back to intalio one was by intention. I suggest to commit as is and integrate test into CTF later when we refactor other tests.
Hide
Werner Guttmann added a comment -

Ralf, can you please briefly explain what the changes are to ObjectTracker and MyAppObject ? License chnage ... no, not really. Just a result of copying code from one place to another .... .

Show
Werner Guttmann added a comment - Ralf, can you please briefly explain what the changes are to ObjectTracker and MyAppObject ? License chnage ... no, not really. Just a result of copying code from one place to another .... .
Hide
Ralf Joachim added a comment -

I didn't thought that I need to explain that changes as they are quite obvious in patch file.

  • ObjectTracker: return result of method call instead of storing it in a variable only to return it.
  • ObjectTracker: removed unneccessary compare with true ' if (hasMaterialized == true)'
  • MyAppObject: removed methods of Persistent interface prviously commented out

Please also commit test case as is under src/bugs to not forget it at CTF refactoring.

Show
Ralf Joachim added a comment - I didn't thought that I need to explain that changes as they are quite obvious in patch file.
  • ObjectTracker: return result of method call instead of storing it in a variable only to return it.
  • ObjectTracker: removed unneccessary compare with true ' if (hasMaterialized == true)'
  • MyAppObject: removed methods of Persistent interface prviously commented out
Please also commit test case as is under src/bugs to not forget it at CTF refactoring.
Hide
Werner Guttmann added a comment -

I just didn't feel like comparing patch files at work .. . Thanks.

Show
Werner Guttmann added a comment - I just didn't feel like comparing patch files at work .. . Thanks.
Hide
jonwilmoth added a comment -

I'm working with the 1355 patched, trunk codebase (as of 4/16) and althought the 1355 patch no longer requires all independent, lazy-loaded objects to be loaded in a relationship tree, read-only queries are now resulting in updates to the objects at the time db.commit() is called. This is particularly bad considering the value of the course's city independent object is getting nulled out. It appears I don't have permission to reopen 1355.

The original test case (LazyLoadRelationshipTest.testLoadLazyCollectionWithoutLazyOneToOne) can be updated with the following snippet to demonstrate the new issue:

public void testLoadLazyCollectionWithoutLazyOneToOne() throws Exception {

... original test case...

//Make sures there aren't any side effects (i.e. independent objects getting updated)
database = jdoMgr.getDatabase();
database.begin();
query = database.getOQLQuery(oql);
query.bind(1);
queryResults = query.execute(AccessMode.ReadOnly);
course = null;
while (queryResults.hasMore()) { course = (GolfCourse) queryResults.next(); City city = course.getCity(); assertNotNull("Golf Course no longer has a relationship to independent object not loaded above", city); assertEquals("GolfCourse's associated independant city has changed!", new Long(1), city.getId()); }
database.commit();
database.close();
}

Show
jonwilmoth added a comment - I'm working with the 1355 patched, trunk codebase (as of 4/16) and althought the 1355 patch no longer requires all independent, lazy-loaded objects to be loaded in a relationship tree, read-only queries are now resulting in updates to the objects at the time db.commit() is called. This is particularly bad considering the value of the course's city independent object is getting nulled out. It appears I don't have permission to reopen 1355. The original test case (LazyLoadRelationshipTest.testLoadLazyCollectionWithoutLazyOneToOne) can be updated with the following snippet to demonstrate the new issue: public void testLoadLazyCollectionWithoutLazyOneToOne() throws Exception { ... original test case... //Make sures there aren't any side effects (i.e. independent objects getting updated) database = jdoMgr.getDatabase(); database.begin(); query = database.getOQLQuery(oql); query.bind(1); queryResults = query.execute(AccessMode.ReadOnly); course = null; while (queryResults.hasMore()) { course = (GolfCourse) queryResults.next(); City city = course.getCity(); assertNotNull("Golf Course no longer has a relationship to independent object not loaded above", city); assertEquals("GolfCourse's associated independant city has changed!", new Long(1), city.getId()); } database.commit(); database.close(); }
Hide
Werner Guttmann added a comment -

Jon, as already mentioned on the mailing list, can you please create a new issue for this (un) related problem, and attach a minimal test case ? I'll have a look at the issue once you have created the new issue and attached the test case.

Show
Werner Guttmann added a comment - Jon, as already mentioned on the mailing list, can you please create a new issue for this (un) related problem, and attach a minimal test case ? I'll have a look at the issue once you have created the new issue and attached the test case.

People

Vote (0)
Watch (1)

Dates

  • Created:
    Updated:
    Resolved: