« Code of Ethics for Government Service | Main | Fault loading »

Fault Loading and UserTransactions

(19:35:07) saintx: Tests run: 81, Failures: 0, Errors: 0, Skipped: 0

(19:35:08) saintx: [INFO] -------------------------------------------------------

(19:35:08) saintx: [INFO] BUILD SUCCESSFUL

(19:35:08) saintx: [INFO] -------------------------------------------------------

(19:35:08) saintx: [INFO] Total time: 19 seconds

(19:35:14) saintx: w00t.

(19:37:19) saintx: I never did figure out how to load an object with more than one collection-valued reference except by using EAGER loading. Fetch plans led to these very ugly ConcurrentModificationExceptions.

(19:54:15) dain: saintx: are you executing the query and inspecting the objects in the same transaction?

(19:54:29) dain: if not, you execute the query and detach the objects

(19:54:43) saintx: dain: no, not inspecting the objects.

(19:54:53) dain: then when you try to inspect them, you can't "fault load" the collections

(19:54:56) saintx: There's something going on with cyclic cascades, I think.

(19:54:58) dain: so you get null

(19:55:17) dain: ya the cascade stuff is tricky to get right

(19:55:19) saintx: "fault load" <-- define, please :)

(19:55:23) saintx: dain: sure is.

(19:55:45) dain: say you execute a query to load all orders

(19:55:52) saintx: I could fix the problem by flagging both ends of the M-M as Eager, but that's not the solution for the long term.

(19:55:57) dain: then you iterate over them and look at the line items

(19:56:01) saintx: yeah

(19:56:10) dain: in the first query you only load the order table

(19:56:19) saintx: correct.

(19:56:34) dain: when you start looking at order.getLineItems().get

(19:56:42) saintx: You get null pointer.

(19:56:42) dain: (0).getName

(19:56:54) dain: the system will fault load the line items

(19:57:08) dain: you only get null if you have a detached object

(19:57:11) saintx: Is this in the transaction--in the query method?

(19:57:35) dain: I don't understand the question

(19:57:48) saintx: In the first query you get the order table.

(19:57:54) dain: as long as the objects are attached you get fault loading

(19:58:01) saintx: Right.

(19:58:20) dain: if you commit the tx all of the orders are detached and you can't fault load the lineitems

(19:58:35) saintx: So, if I return the List results from the query, the transaction ends and the items are detached, because I'm using a TRANSACTIONAL context.

(19:58:56) dain: it is because your transactions are too small

(19:59:14) dain: typically, you want one tx per unit of work (typically a web request)

(19:59:20) saintx: I'm not "commiting" anything explicitly. Just fetching a list of objects and returning them to my test case.

(19:59:37) saintx: okay, that's good to know.

(19:59:56) dain: sure, but you are still committing because your access is wrapped by a stateless bean

(20:00:26) saintx: Yes, it's implicit. The "commit" happens when the method ends and returns the list, I assume.

(20:00:30) dain: you have two options to extends the transaction.. move some of your test logic to a stateless bean, or use the UserTransaction in your test

(20:01:00) saintx: Interesting--what's a UserTransaction?

(20:01:21) dain: my point is that regardless of an implicit or explicit commit, you are controlling the commit of the transaction

(20:01:27) saintx: Sure, I agree.

(20:01:54) dain: javax.transaction.UserTransaction

(20:02:10) dain: it is a dumbed down interface to the TransactionManager

(20:02:29) saintx: What I've been doing is calling a query with a LEFT JOIN FETCH on one of the collection valued references, then checking to see if the merge cascading works, then starting over for a different collection valued reference until I've covered all of them for a class.

(20:02:46) saintx: dain: got it. I'll look at that.

(20:03:34) saintx: My most complex entity has five collection valued references to other entities.

(20:03:45) dain: here is some tests that use user transaction https://svn.apache.org/repos/asf/openejb/trunk/openejb3/itests/openejb-itests-client/src/main/java/org/apache/openejb/test/entity/cmr/OneToOneTests.java

(20:03:55) saintx: dain: awesome

(20:04:38) dain: it is the cmp test that verifies that collection references work

(20:05:04) dain: I had to control the transactions so my objects don't detach

(20:05:43) saintx: this is how I was doing it: http://rifers.org/paste/show/6404

(20:05:55) saintx: mgr is my stateless session bean

(20:08:29) dain: in a normal web application, you typically read in the request and convert the strings to real data types in the servlet, then you hand off the data to a stateless session bean that updates your database

(20:08:45) saintx: sure

(20:09:13) saintx: I'm looking for where you define "ds". Must be in AbstractCMRTest?

(20:09:32) dain: then either that same bean or a new one, query the JPA system for the reponse and assures that all fields are loaded

(20:09:48) dain: that data is detached and stuffed in the request map

(20:10:08) dain: then a jsp, velocity, or template system generates html

(20:10:12) saintx: yep

(20:10:29) dain: so I try use the same model in my tests

(20:11:11) dain: basically, the tests should look like your main code will

(20:12:51) dain: saintx: I don't recommend going directly to the database like that test does

(20:13:05) dain: that test is verifying the correctness of the CMP engine

(20:13:27) saintx: This isn't that much different. If you ignore the servlet part, you make a new bean, populate its entity references, persist it, check to see if those entities made it into the database, then get a copy of that bean from the database, change some values in it and its references, merge the new copy, check out another instance of the bean, check it and its references to ensure they have been changed, then remove and make sure the appropriate obj

(20:13:38) saintx: dain: clear.

(20:14:08) dain: the one difference, is I control the transaction scope

(20:14:18) saintx: Yes, which is nice.

(20:14:20) dain: so I can verify references that are fault loaded

(20:14:29) saintx: Which simplifies things quite a bit.

(20:14:52) saintx: Fault loading isn't mentioned in the book : )

(20:14:55) dain: ya, your code looks like you are struggling against JPA (because of the transaction scoping)

(20:14:58) dblevins hat den Raum verlassen (quit: Read error: 110 (Connection timed out)).

(20:15:17) saintx: I am.

(20:15:20) dain: I think you will be much happier with slightly bigger transactions

(20:15:25) saintx: Which is frustrating.

(20:15:29) saintx: Cool.

(20:16:05) dain: all this stuff works better when you start thinking of "units of work"

(20:16:23) dain: those become your natural transaction boundaries

(20:16:52) saintx: Yeah, this entire effort screams for another abstraction layer--my test class is >1450 lines of code.

(20:17:36) dain: BTW you should take a look at the Oreilly "RESTful Web Services" book

(20:17:54) dain: it fits nicely with the data modeling work you are doing

(20:17:56) saintx: I thought about breaking it out but then would have to reload the database--so I'll probably create a class that grabs one db in memory and then holds on to it for all test classes to reference so it doesn't take so long creating and tearing down the db for each test case.

(20:18:12) saintx: excellent--I'll take a look at that right away.

TrackBack

TrackBack URL for this entry:
http://blog.lib.umn.edu/cgi-bin/mt-tb.cgi/59671

Post a comment

(If you haven't left a comment here before, you may need to be approved by the site owner before your comment will appear. Until then, it won't appear on the entry. Thanks for waiting.)