> 2. In TX_REQUIRED, if the method invocation came w/o > transaction > (oldTransaction == null) we start a new transaction. > Then, in 'finally' > block we try to commit this transaction through > Transaction.commit(). I > understand why we don't use > TransactionManager.commit(), because our > thread may no longer be associated with the > newTransaction.
Thread association is an implicit system level way to carry a transaction or for that matter any other object (think security). Its sole purpose in life is to pass *random* information through a typed interface. e.g. the association of the tx to the thread permits us to read that information behind the "wall" of the API, even if the API doesn't explicitely declare that information. This is a system construct, superior for example to the lame duck aka JINI that calls for explicit coding of tx in the API doSomething(..., TX). FINE, however we have a superior way to do it in JBoss, we can pass the transaction information THROUGH the API in the "INVOCATION". THEREFORE building anything that relies on the system presence of the association assumes that all parties are doing the right thing with that association, which is not the case here. We work from the tx in the message. The rest is TM specific quirks > Problem arises with Tyrex when > > (This happened when a servlet in Jetty was calling 2 > methods of a bean > consequently) > Thread T calls a bean 2 times, both methods have > TX_REQUIRED. Initially > thread T is not associated with a transaction (i.e. > threadTx is null) > > invocation 1 > GenericProxy gets current thread transaction (null) > and invokes the bean. > oldTransaction is null, thus according to (2) > newTransaction > (Tx1) is started and then committed through > Transaction.commit(). Thread T > is still associated with Tx1 if Tyrex is the TM. When > we reach 'finally' > block that has to reinstate the threadTx, nothing > happens because threadTx > is null, so T leaves the interceptor associated with > Tx1 which is > committed. In the early EJBoss I separated these calls into tx.commit/tx.rollback and then "suspendAssociation" "resumeAssociation", because that semantic is clearer than the fuzzy "if you commit with this or that we dis-associate and what not". At this point a simple way to solve this is to explicitely dis-associate thread if the tx is demarcated (commit/rollback) > invocation 2 > GenericProxy gets the transaction associated with the > current thread, i.e. > Tx1 and calls the bean with this tx context. > oldTransaction == Tx1, the > transaction manager tries to resume the transaction > ---> Exception, the > transaction is already committed. The Transacation manager interprets the fuzzy "resume" however it wants, resume should only be an association of the tx to the thread and basta, nothing else, it should not *think* about the status of the tx at all i have argued in the past with OLE that THIS IS NOT A LIFECYCLE EVENT ON THE TRANSACTION, CLEARLY CLEARLY CLEARLY, SO THE TM SHOULD NOT ****THINK**** ABOUT THE TX IT SHOULD JUST ****RESUME ASSOCIATION****. Sorry to talk all in cap my keyboard got stuck. > So, the lesson is, JTA/TM is a crappy spec interpreted left and right ? I should be on that commitee writing the transaction spec and I would clean up this clear mess. >the thread has to leave the > interceptor with exactly > the same tx association it came in. Because threadTx > can be null, we don't > always resume threadTx, so if threadTx was null when > the thread came in, > it must be null when the thread leaves, so if the > transaction manager does > not clean tx thread association through > Transaction.commit() and > Transaction.rollback(), it must be cleaned by the > interceptor through > tm.suspend() to make threadTx null again. Yes that would work, always dis-associating the thread if commited/rollback seems like a good idea, making that call explicit as opposed to buried in the interpretations of the spec is a good idea, > The changes to the interceptor are trivial (always > call tm.suspend, even > if committing or rolling back the new transcation). No, be careful there cowboy do you really want to call suspend() (in the dis-association sense) if your transaction is not commited? Could be. In jboss it is the recommend way because we pass the information explicitely, in integration with other parties... I don't know, if they take our information ok if not they will rely on the system level association and you should preserve the association.Think about the EJB spec it actually SAYS you should resume association if the tx is still there. in clear ONLY suspend the system association IF you commited or rolledback yourself (as opposed to the wrong "all the time *even if* rollback". Do we have agreement? > Also, in > TX_SUPPORTS, there has to be > if (oldTransaction != null) > guard befor tm.resume(oldTransaction) is called, > otherwise Tyrex is pissed > off :) Tyrex is a crappy TM, I would rather see FastTM extended to DistributedTM in JBoss. marcf ______________________________________________________________________ View this jboss-dev thread in the online forums: http://jboss.org/forums/thread.jsp?forum=66&thread=5820 _______________________________________________ Jboss-development mailing list [EMAIL PROTECTED] https://lists.sourceforge.net/lists/listinfo/jboss-development
