I just did a test on AS6 with 2.1.0.Beta3 and 2.1.0.GA, and the test is failing after the upgrade.
The test is about expiring setting a transaction with a timeout = 5 seconds:
UserTransaction ut = sessionCtx.getUserTransaction();
Then we receive a message (that was sent previously), and wait 10 seconds (wait > timeout)
catch (InterruptedException ignored)
We then send a message:
MessageProducer p = s.createProducer(queue);
Message m = s.createTextMessage("100");
catch (JMSException expected)
But the message isn't supposed to be accepted. (An exception should be throwed and the message disposed).
I remeber we delt with this before. Andy fixed it.. but I'm not sure why it has regressed.
I guess we will have to add the AS6 testsuite to the release procedures.
We screwed up by at least not setting the AS6 to CR1, or we would have captured this error otherwise.
What's probably happening is the same thing that happened before. Something is probably creating a new TX instead of keeping it invalid for the user transaction.
I believe there's a big thread on the dev-forum about this fix also. (XA Behaviour or something like that).. I will look of it later if we need to.
I thinkl the problem may be with the test, this is what happens:
In HornetQRAManagedConnection we hold 2 sessions an xa session and a non xa session. we also hold a flag that indicates whether or not we are currently in a managed transaction. This will be set to tru when the App server starts an xa tx and back to false when it is commited or rolled back. depending on what this is set to we return either of the sessions.
In the test the transaction manager rolls back the transaction and sets the flag to false so the next session used for the following send in non xa, meaning it will send with no problems.
Maybe Jesper can comment.
Tim,I'm a bit concerned with this TX issue.The TX manager tells us: End(Success) and then Rollback(XID)...We have no way to differentiate a failure, and keep the TX alive from a clean End / Rollback.We had fixed it before by https://jira.jboss.org/browse/HORNETQ-328But then we introduced the dual session behaviour... what made the issue reapear.. That means.. the RASession still have the dual behaviour that aren't supposed to happen.I don't know how we could exit this route. The only way I can think of is by changing the Transaction Manager.. or have something telling us the session is back on pool and it can be cleared to reuse.
So, a summary of what's going on:
- TransactionActiveUnitTestCase is validating if timeouts are working properly with User transactions.
- HornetQ Resource Adapter has two real sessions on every RASession.
* As long as the TM end(Success) the Session is back to NonTransacted.
(Since RASessions are supposed to behave non transaction when the TX is not enlisted).
- When the TX times out, the TM will call end (Success) and Rollback(XID)
* However the user still using that TX (Invalid now)
We should make a clear distinction of the Session, and keep using it as XA until the end.
Or the TM should call end(Failure). and something should clear the session before it returns to the pool.
Why did we introduce two sessions on the RA at the end?
The whole issue was not knowing when the session returned to the pool, so we could clear it properly.
Having two sessions defeated the purposed of the test I added:
and now we have the same issue back, through RA now.
How can we distinguish when the user called close() at the RAConnection, so we can clear the Session state, and have it ready to be reused with clear state?
The dual session was addeed as it needs to differentaite between being an xa session ot not but stil lpooled. Jeff added this as far as i know. Why dont i add a thread local for this setting that gets set at the beginning and will outlive the rollback/end. I think its all called within the same thread?
ok, my understanding is this:
A managed connection and its session(which is a jca spi) needs to be cached for obvious reasons but still support both xa and non xa sessions (actually it supports local tx's to). Because of this we hold 2 sessions one xa and one non xa. The JCA will call getXaResource on the managed connection which must always return the same resource (as per the spec) and call start, end, rollback, commit etc on it.
We intercept these calls and set a flag on the managed connection to say it is being used as part of a xa transaction, if this is the case when the JCA calls getSession we know to return the cached xa session. If the JCA does not call getXaResource and start a tx we know that we should return the non xa session.
Most of this works fine, however we set this flag back to false when either rollback or commit is called ready for the next component that asks for this managed connection. This means that if a user rolls back or commits something on the tx and then tries to say send another message, the sent message will be sent using the non xa session and succeed, rather than using the xasession and fail because of obvious xa semantics.
I think that all these calls will be done on the same thread so we could set a thread local (boolean) flag on xa start and use this until the thread completes. I need to check this tho as i am not 100% clear if this is the case or not.
hope thats a bit clearer.