It's very difficult to tell what is happening here.
It could be a database locking problem. You can test this using SQL commands outside the application server.
Or it could be a JBoss locking problem, as JBoss also operates a locking strategy on entity beans.
Or it could be a locking problem on the message queues if placing the message from MDB1 to MDB2 on the queue is included in the uncommitted transaction.
And how are you preventing the commit executing in the first MDB ? Normally, the transaction would automatically commit once the onMessage() method runs to completion.
Either way, the real problem is that you are trying to carry out a second operation (in the second MDB) on the entity bean before completing the first.
I would suggest two alternatives :-
1. Perform a commit in the first MDB (which should include the three operations of removing Message 1 from the queue, updating the entity bean and enqueing the message to MDB2). Then MDB2 has a clean operation.
2. Refactor so that the work done in MDB2 is performed iin MDB1.
1 - if MDB1 send message to MDB2 in one of it's onMessage()
used method , how can you gurentee that MDB1 commit before MDB2
will start ?
2- both MDBs are using the same Queue (different selector) with
AUTO_ACKNOWLEDGE , is that adding light ?
I guess that you could get a race between MDB2 starting and MDB1 committing if (a) you use a file based JMS persistence manager and (b) you are not including the JMS messages in the transaction. Then it is possible for the thread running MDB2 to start before the thread in MDB1 has finished.
That would suggest that, if you persevere with this architecture, you should use a JDBC based persistence manager and include handling JMS messages within the transaction. That involves getting a reference to the Transaction Manager and calling the begin() and commit() methods on it.
Making message handling transactional also avoids problems if the database commit fails but the messages are still processed.
I think, however, that refactoring would almost certainly be a quicker and more reliable method of resolving the problem.
If you can tell me what your application is trying to do, I may be able to suggest an alternative design pattern.
it's ok if thread2 will not be able to see the changed data
before the commit,why it doesn't wait() to the commit,why instead it rollback ?!
i guess that the second tx didn't wait at all (for sure not till timeout) since
it was marked for rollback ,and it was marked for rollback because of
a deadlock which has no trace on the jboss log , as i get deeper in my system i found that deadlocks may occur (and even saw one,after
code change) , i assume that jboss just 'forgot' on a certain flow to trace
I have found in my code a 'catch(Excetion e)' around the the code where the deadlock tookplace and the tx was marked for rollback,the catch has no trace inside it,and there for i could never know that there was a rollback as to a deadlock,in the followed lines i only got TransactionRollBackedException without any good explantion.
As to JBoss logs,on 3.2.5,the DeadlockDetector doesn't trace the deadlock but only throw it as exception ,which means that bad code of exception handling (as mine) will lose this very critical piece of information , that's the code
// removeWaiting should be cleaned up in acquire
String msg = "Application deadlock detected,
//NO TRACE HERE !!!
throw new ApplicationDeadlockException(msg, true);
Adrian , this might be good to pass to developers to add a trace :-) ,