JPA and transactions in a Java SE environment
jduprezFeb 14 2011 — edited Feb 21 2011Hello,
first, I haven't found a forum dedicated to JPA per se: {forum:id=972} contains a lot of JPA questions, but mosly in the context of the JEE platform, where transaction context is managed by the container. And {forum:id=1050} deals with DB interactions at a lower level, and does not contain many JPA topics. I concluded that "Java Programming" was the best fit for discussing this, let me know if you know otherwise.
Second, the problem's statement:
I have a JSE application, including a GUI, that uses JPA (with EclipseLink provider) to access a JavaDB database. Originally, all DB interactions were done in a single thread, off-loaded from the GUI's Event Dispatch Thread, and there were no explicit transaction management.
Lately this application has started supporting "notifications" from a couple of other apps. The JPA application now has several "server" threads that handle those notifications, some of which end up interacting with the DB too.
Long story short, I now have a JSE app under development with concurrent threads accessing the DB. And testing now starts exhibiting "strange" behaviors; I'm sorry I don't have an actual trace to push here (will add them if needed), but this goes along EclipseLink complaining about concurrent transactions (well that at least is quite explicit), or sometimes throwing NPEs in internal methods, or sometimes threads seeing apparently inconsistent values of the same entity.
We started adding explicit transaction management, but this has several drawbacks:
- the hammer version of this is having explicit entityManager.getTransaction().begin()/commit() ) in various places. That's a nuisance for readability, and it's a bit hard to decide what is the appropriate location.
- I am not sure I have an extensive test harness to exercise on this application in terms of concurrent load, and I don't know which kinds of effect concurrent code will see on various unforeseen problems (e.g. on rollback, locking,...)
- We haven't completed this task yet, but so far the part I've done hasn't solved most of the intermittent problems yet (the only thing my explicit tx management has improved is consistent visibility, explicitly committed changes are now visible to other threads, but even then maybe I have just been lucky).
Before going on, I'm wondering:
1) what is the recommended approach for dealing with that (JPA transactions in JSE):
- putting transaction.begin() at the bottom of the call stack (in the server thread's "handleClient" method), before invoking the business logic, and commit() at the same place, on completion of the BL method(s)? The drawback is that I then have to expose the EntityManager to this "handle client" layer, whereas so far the JPA plumbing has all been hidden in a much lower DAO layer.
- hiding transaction.begin/commit within the DAO layer is too fine-grained: it ignores the fact that some of the BL involves interactions that span more than one DAO methods/classes.
JEE for example, implements mostly the first approach, with a bunch of techniques (in particular, annotations) enabling to declare finer-grained "nested" transaction demarcation/grouping per EJB method.
2) Where should I read to find out about how the JPA implementation will behave with regards to transactions: I mean, it's not clear to me whether e.g. locking policy is specified at the JPA spec level, or to be found within the provider's specific documentation.
Thank you for your help, and best regards,
J.