ari.meyer (2) [Avatar] Offline
#1
Hi,

I have the seemingly simple case wherein I want to log messages to a database. As you say in 6.1 Understanding transactions [REQUIRES_NEW]:

"You should use it if you need a transaction but don’t want a rollback to affect the client. Also use this value when you don’t want the client’s rollback to affect you. Logging is a great example. Even if the parent transaction rolls back, you want to be able to record the failure in your logs. On the other hand, failing to log a minor debugging message should not roll back your entire transaction and the problem should be localized to the logging component."

So I've tried using REQUIRES_NEW, but when invoked from an enclosing transaction, this results in an apparent database deadlock, and my app hangs. I assumed, somewhat naively, that txn A would be suspended while txn B executes, then control would return to A, but this is obviously incorrect. I then found this: http://java.sys-con.com/node/204688?page=0,1 ("Deadlocks in J2EE"), wherein the "Cross-Resource Deadlock #2: Single-Thread, Multiple Conflicting Database Connections" describes my issue.

So how can write my LoggingService using REQUIRES_NEW (assuming proper transaction suspension), and consistently avoid deadlocks? As it stands, I have to restrict usage to only places outside of an enclosing transaction, which makes LoggingService no longer a service that can be used anywhere, without further consideration.

I am now considering changing the implementation to use JMS (or perhaps even just start another thread), hoping that this would effectively decouple the 2 transactions. Is this an appropriate approach, even though it seems overkill? How can you implement this, as you described, and ensure that deadlocks will be avoided?

Thanks,
Ari

Message was edited by:
ari.meyer