BTM + Spring + ActiveMQ - JMS session is not closed properly on broker connection failure

classic Classic list List threaded Threaded
8 messages Options
Reply | Threaded
Open this post in threaded view
|

BTM + Spring + ActiveMQ - JMS session is not closed properly on broker connection failure

Filipp Gunbin
Hello,

I have a problem with BTM, I've tracked it down to a (rather clumsy) test case
which is attached with its Maven project.

I ran into this problem when I restarted broker while my app was running
and it stopped receiving messages. It turned out that a session was
still residing in ActiveMQConnection object after broker restart, it was
not registered anywhere in Bitronix session wrappers (only in the
connection which was cached) and that session received messages which
then could not be delivered to my app's message listeners.

In short, the description is:

The problem occurs when the broker stops while message listener in
Spring DefaultMessageListenerContainer hasn't committed yet. The session
is not actually removed from the ActiveMQConnection while its enclosing
JmsPooledConnection is considered closed and returned to the pool.

An ugly workaround is to force connection refresh - it makes the test
case pass.

Spring version: 3.0.5
Bitronix version: 2.1.1
ActiveMQ version: 5.4.2

I debugged both the successful transaction commit scenario and the
failing one, here is (roughly) what happens. Maybe it will help in some way.

1. Successful commit flow.

AbstractPollingMessageListenerContainer.doReceiveAndExecute()
BitronixTransactionManager.commit()
BitronixTransaction.commit()
post commit synchronizations
DeferredReleaseSynchronization sets state to IN_POOL for session
DualSessionWrapper.stateChanged() calls ActiveMQSession.close() and the
ActiveMQ session closes and removes itself from a connection

Everything OK here.

2. Failing commit scenario.

AbstractPollingMessageListenerContainer.doReceiveAndExecute()
BitronixTransactionManager.commit()
BitronixTransaction.commit()
BitronixTransaction.delistUnclosedResources() fails due to the
following:
    BitronixTransaction.delistResource()
    XAResourceManager.delist()
    XAResourceHolderState.end() (here resource is marked as failed after
    exception below)
    TransactionContext.end()
    TransactionContext.beforeEnd()
    synchronizations
    consumer.acknowledge() (here exception is thrown)
BitronixTransaction.rollback() - there's nothing to rollback (because
the resource is marked as failed)
post completion synchronizations
DeferredReleaseSynchronization sets state to IN_POOL for session
DualSessionWrapper.stateChanged() calls ActiveMQSession.close() and _it
registers its dispose on txContext.afterRollback_, because it thinks its
txContext is still in transaction. This is where session is not actually
closed. Rollback was not performed on a failed resource and
transactionId is still present in TransactionContext

So the main points for the failing scenario are:
1. consumer acknowledge causes the resource to be marked as failed
(because connection to the broker is not available)
2. rollback for the failed resource does nothing
3. session close on DualSessionWrapper.stateChanged() (called from
DeferredReleaseSynchronization) does not actually close the original
session

Thanks in advance for any help!

Filipp Gunbin
---------------------------------------------------------------------
To unsubscribe from this list, please visit:

    http://xircles.codehaus.org/manage_email

btm-jms-session-close-problem.tgz (5K) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: BTM + Spring + ActiveMQ - JMS session is not closed properly on broker connection failure

Ludovic Orban-2
I must confess I didn't spend lots of time investigating your problem using the attached sample code but it looks like everything is working as it should at first sight.

Let me answer your list of the main points for the failing scenario:

1. consumer acknowledge causes the resource to be marked as failed (because connection to the broker is not available)

Looks fair and actually is ActiveMQ's job.


2. rollback for the failed resource does nothing

Yes. As logged, BTM assumes that a resource failing deslitment (ie: when XAResource.end() throws an exception) as an unilateral rollback so the whole transaction has to be rolled back and the resource is marked as failed.


3. session close on DualSessionWrapper.
stateChanged() (called from DeferredReleaseSynchronization) does not actually close the original session
What makes you believe that? When stateChanged() is called on DualSessionWrapper the latter immediately switches the state to CLOSED which triggers stateChanged() again to close the session, xaSession, producers and consumers.


It looks to me like both BTM and ActiveMQ are reacting the way they're supposed to when they face a connection failure. I fail to see where your problem is so could you please give more details about what you're observing and what you think is going wrong?


2011/9/9 Filipp Gunbin <[hidden email]>
Hello,

I have a problem with BTM, I've tracked it down to a (rather clumsy) test case
which is attached with its Maven project.

I ran into this problem when I restarted broker while my app was running
and it stopped receiving messages. It turned out that a session was
still residing in ActiveMQConnection object after broker restart, it was
not registered anywhere in Bitronix session wrappers (only in the
connection which was cached) and that session received messages which
then could not be delivered to my app's message listeners.

In short, the description is:

The problem occurs when the broker stops while message listener in
Spring DefaultMessageListenerContainer hasn't committed yet. The session
is not actually removed from the ActiveMQConnection while its enclosing
JmsPooledConnection is considered closed and returned to the pool.

An ugly workaround is to force connection refresh - it makes the test
case pass.

Spring version: 3.0.5
Bitronix version: 2.1.1
ActiveMQ version: 5.4.2

I debugged both the successful transaction commit scenario and the
failing one, here is (roughly) what happens. Maybe it will help in some way.

1. Successful commit flow.

AbstractPollingMessageListenerContainer.doReceiveAndExecute()
BitronixTransactionManager.commit()
BitronixTransaction.commit()
post commit synchronizations
DeferredReleaseSynchronization sets state to IN_POOL for session
DualSessionWrapper.stateChanged() calls ActiveMQSession.close() and the
ActiveMQ session closes and removes itself from a connection

Everything OK here.

2. Failing commit scenario.

AbstractPollingMessageListenerContainer.doReceiveAndExecute()
BitronixTransactionManager.commit()
BitronixTransaction.commit()
BitronixTransaction.delistUnclosedResources() fails due to the
following:
   BitronixTransaction.delistResource()
   XAResourceManager.delist()
   XAResourceHolderState.end() (here resource is marked as failed after
   exception below)
   TransactionContext.end()
   TransactionContext.beforeEnd()
   synchronizations
   consumer.acknowledge() (here exception is thrown)
BitronixTransaction.rollback() - there's nothing to rollback (because
the resource is marked as failed)
post completion synchronizations
DeferredReleaseSynchronization sets state to IN_POOL for session
DualSessionWrapper.stateChanged() calls ActiveMQSession.close() and _it
registers its dispose on txContext.afterRollback_, because it thinks its
txContext is still in transaction. This is where session is not actually
closed. Rollback was not performed on a failed resource and
transactionId is still present in TransactionContext

So the main points for the failing scenario are:
1. consumer acknowledge causes the resource to be marked as failed
(because connection to the broker is not available)
2. rollback for the failed resource does nothing
3. session close on DualSessionWrapper.stateChanged() (called from
DeferredReleaseSynchronization) does not actually close the original
session

Thanks in advance for any help!

Filipp Gunbin

---------------------------------------------------------------------
To unsubscribe from this list, please visit:

   http://xircles.codehaus.org/manage_email


Reply | Threaded
Open this post in threaded view
|

Re: BTM + Spring + ActiveMQ - JMS session is not closed properly on broker connection failure

Filipp Gunbin
Ludovic,
Thank you for the quick answer.

Ludovic Orban <[hidden email]> writes:

>
> 3. session close on DualSessionWrapper.
>
>     stateChanged() (called from DeferredReleaseSynchronization) does not actually close the original session
>
> What makes you believe that? When stateChanged() is called on DualSessionWrapper the latter immediately switches the state to CLOSED which triggers
> stateChanged() again to close the session, xaSession, producers and
> consumers.

I've described it in details in failing commit scenario. In short, the
transactionId is not reset to null in TransactionContext and that makes
ActiveMQSession think it is still in transaction when it does
close(). And it registers its dispose method for later execution (which
never happens because rollback is already done) instead of immediate
operation.
That seems quite logical from the ActiveMQ's point of view. Maybe the
transactionId for a failed resource needs to be reset somewhere in BTM,
but that's just a rough guess.

>
> It looks to me like both BTM and ActiveMQ are reacting the way they're supposed to when they face a connection failure. I fail to see where your problem is
> so could you please give more details about what you're observing and
> what you think is going wrong?

The main problem is that unclosed session is retained in
ActiveMQConnection, it may receive messages (and does so), but no other
component will ever see it until connection reset (when all sessions are
forced to close). So the messages do not get consumed by the application
message listeners.

I've described that in slightly more details in the first paragraphs of
the original post.

Filipp.


>
> 2011/9/9 Filipp Gunbin <[hidden email]>
>
>     Hello,
>    
>     I have a problem with BTM, I've tracked it down to a (rather clumsy) test case
>     which is attached with its Maven project.
>    
>     I ran into this problem when I restarted broker while my app was running
>     and it stopped receiving messages. It turned out that a session was
>     still residing in ActiveMQConnection object after broker restart, it was
>     not registered anywhere in Bitronix session wrappers (only in the
>     connection which was cached) and that session received messages which
>     then could not be delivered to my app's message listeners.
>    
>     In short, the description is:
>    
>     The problem occurs when the broker stops while message listener in
>     Spring DefaultMessageListenerContainer hasn't committed yet. The session
>     is not actually removed from the ActiveMQConnection while its enclosing
>     JmsPooledConnection is considered closed and returned to the pool.
>    
>     An ugly workaround is to force connection refresh - it makes the test
>     case pass.
>    
>     Spring version: 3.0.5
>     Bitronix version: 2.1.1
>     ActiveMQ version: 5.4.2
>    
>     I debugged both the successful transaction commit scenario and the
>     failing one, here is (roughly) what happens. Maybe it will help in some way.
>    
>     1. Successful commit flow.
>    
>     AbstractPollingMessageListenerContainer.doReceiveAndExecute()
>     BitronixTransactionManager.commit()
>     BitronixTransaction.commit()
>     post commit synchronizations
>     DeferredReleaseSynchronization sets state to IN_POOL for session
>     DualSessionWrapper.stateChanged() calls ActiveMQSession.close() and the
>     ActiveMQ session closes and removes itself from a connection
>    
>     Everything OK here.
>    
>     2. Failing commit scenario.
>    
>     AbstractPollingMessageListenerContainer.doReceiveAndExecute()
>     BitronixTransactionManager.commit()
>     BitronixTransaction.commit()
>     BitronixTransaction.delistUnclosedResources() fails due to the
>     following:
>        BitronixTransaction.delistResource()
>        XAResourceManager.delist()
>        XAResourceHolderState.end() (here resource is marked as failed after
>        exception below)
>        TransactionContext.end()
>        TransactionContext.beforeEnd()
>        synchronizations
>        consumer.acknowledge() (here exception is thrown)
>     BitronixTransaction.rollback() - there's nothing to rollback (because
>     the resource is marked as failed)
>     post completion synchronizations
>     DeferredReleaseSynchronization sets state to IN_POOL for session
>     DualSessionWrapper.stateChanged() calls ActiveMQSession.close() and _it
>     registers its dispose on txContext.afterRollback_, because it thinks its
>     txContext is still in transaction. This is where session is not actually
>     closed. Rollback was not performed on a failed resource and
>     transactionId is still present in TransactionContext
>    
>     So the main points for the failing scenario are:
>     1. consumer acknowledge causes the resource to be marked as failed
>     (because connection to the broker is not available)
>     2. rollback for the failed resource does nothing
>     3. session close on DualSessionWrapper.stateChanged() (called from
>     DeferredReleaseSynchronization) does not actually close the original
>     session
>    
>     Thanks in advance for any help!
>    
>     Filipp Gunbin
>     ---------------------------------------------------------------------
>     To unsubscribe from this list, please visit:
>    
>        http://xircles.codehaus.org/manage_email

---------------------------------------------------------------------
To unsubscribe from this list, please visit:

    http://xircles.codehaus.org/manage_email


Reply | Threaded
Open this post in threaded view
|

Re: BTM + Spring + ActiveMQ - JMS session is not closed properly on broker connection failure

Ludovic Orban-2
Ok, so here is the flow from BTM's perspective:

TransactionManager.commit()
XAResource.end() // fails and throws XAException
XAResource.rollback()
XASession.close()
throw RollbackException()

and your problem is that the ActiveMQ session stays in limbo because it believes it's not closed, just because BTM called rollback on the XAResource it before closing the session.

I'm sorry but that looks like an ActiveMQ bug to me. In their end() implementation, it appears that calling setXid(null) in a finally block would solve your issue but I don't know if that wouldn't have unwanted side effects.

Another reason why I think it's their bug is because expecting the rollback to happen after the session is closed sounds illogical to me.

I suggest your to report this problem to the ActiveMQ maintainers, but I'm open to discuss the issue furthermore if needed.



2011/9/9 Filipp Gunbin <[hidden email]>
Ludovic,
Thank you for the quick answer.

Ludovic Orban <[hidden email]> writes:

>
> 3. session close on DualSessionWrapper.
>
>     stateChanged() (called from DeferredReleaseSynchronization) does not actually close the original session
>
> What makes you believe that? When stateChanged() is called on DualSessionWrapper the latter immediately switches the state to CLOSED which triggers
> stateChanged() again to close the session, xaSession, producers and
> consumers.

I've described it in details in failing commit scenario. In short, the
transactionId is not reset to null in TransactionContext and that makes
ActiveMQSession think it is still in transaction when it does
close(). And it registers its dispose method for later execution (which
never happens because rollback is already done) instead of immediate
operation.
That seems quite logical from the ActiveMQ's point of view. Maybe the
transactionId for a failed resource needs to be reset somewhere in BTM,
but that's just a rough guess.

>
> It looks to me like both BTM and ActiveMQ are reacting the way they're supposed to when they face a connection failure. I fail to see where your problem is
> so could you please give more details about what you're observing and
> what you think is going wrong?

The main problem is that unclosed session is retained in
ActiveMQConnection, it may receive messages (and does so), but no other
component will ever see it until connection reset (when all sessions are
forced to close). So the messages do not get consumed by the application
message listeners.

I've described that in slightly more details in the first paragraphs of
the original post.

Filipp.


>
> 2011/9/9 Filipp Gunbin <[hidden email]>
>
>     Hello,
>
>     I have a problem with BTM, I've tracked it down to a (rather clumsy) test case
>     which is attached with its Maven project.
>
>     I ran into this problem when I restarted broker while my app was running
>     and it stopped receiving messages. It turned out that a session was
>     still residing in ActiveMQConnection object after broker restart, it was
>     not registered anywhere in Bitronix session wrappers (only in the
>     connection which was cached) and that session received messages which
>     then could not be delivered to my app's message listeners.
>
>     In short, the description is:
>
>     The problem occurs when the broker stops while message listener in
>     Spring DefaultMessageListenerContainer hasn't committed yet. The session
>     is not actually removed from the ActiveMQConnection while its enclosing
>     JmsPooledConnection is considered closed and returned to the pool.
>
>     An ugly workaround is to force connection refresh - it makes the test
>     case pass.
>
>     Spring version: 3.0.5
>     Bitronix version: 2.1.1
>     ActiveMQ version: 5.4.2
>
>     I debugged both the successful transaction commit scenario and the
>     failing one, here is (roughly) what happens. Maybe it will help in some way.
>
>     1. Successful commit flow.
>
>     AbstractPollingMessageListenerContainer.doReceiveAndExecute()
>     BitronixTransactionManager.commit()
>     BitronixTransaction.commit()
>     post commit synchronizations
>     DeferredReleaseSynchronization sets state to IN_POOL for session
>     DualSessionWrapper.stateChanged() calls ActiveMQSession.close() and the
>     ActiveMQ session closes and removes itself from a connection
>
>     Everything OK here.
>
>     2. Failing commit scenario.
>
>     AbstractPollingMessageListenerContainer.doReceiveAndExecute()
>     BitronixTransactionManager.commit()
>     BitronixTransaction.commit()
>     BitronixTransaction.delistUnclosedResources() fails due to the
>     following:
>        BitronixTransaction.delistResource()
>        XAResourceManager.delist()
>        XAResourceHolderState.end() (here resource is marked as failed after
>        exception below)
>        TransactionContext.end()
>        TransactionContext.beforeEnd()
>        synchronizations
>        consumer.acknowledge() (here exception is thrown)
>     BitronixTransaction.rollback() - there's nothing to rollback (because
>     the resource is marked as failed)
>     post completion synchronizations
>     DeferredReleaseSynchronization sets state to IN_POOL for session
>     DualSessionWrapper.stateChanged() calls ActiveMQSession.close() and _it
>     registers its dispose on txContext.afterRollback_, because it thinks its
>     txContext is still in transaction. This is where session is not actually
>     closed. Rollback was not performed on a failed resource and
>     transactionId is still present in TransactionContext
>
>     So the main points for the failing scenario are:
>     1. consumer acknowledge causes the resource to be marked as failed
>     (because connection to the broker is not available)
>     2. rollback for the failed resource does nothing
>     3. session close on DualSessionWrapper.stateChanged() (called from
>     DeferredReleaseSynchronization) does not actually close the original
>     session
>
>     Thanks in advance for any help!
>
>     Filipp Gunbin
>     ---------------------------------------------------------------------
>     To unsubscribe from this list, please visit:
>
>        http://xircles.codehaus.org/manage_email

---------------------------------------------------------------------
To unsubscribe from this list, please visit:

   http://xircles.codehaus.org/manage_email



Reply | Threaded
Open this post in threaded view
|

Re: BTM + Spring + ActiveMQ - JMS session is not closed properly on broker connection failure

Filipp Gunbin
Do you mean that XAResource should stop thinking it's in a transaction
after its end() is called even if the exception is thrown somewhere in
the process of end()?

Then BTM will mark it as failed and will not call rollback() on it (as
it does now).

(Anyway ActiveMQ's TransactionContext will not allow to call its
rollback() if the transaction is still in progress, there's a check at
the beginning of the method.)

ActiveMQSession will be closed correctly only when TransactionContext is
not in transaction.

If you confirm the above (that logic is OK from the BTM point of view)
I'll post this issue to the ActiveMQ mailing list.

Thanks,
Filipp

Ludovic Orban <[hidden email]> writes:

> Ok, so here is the flow from BTM's perspective:
>
> TransactionManager.commit()
> XAResource.end() // fails and throws XAException
> XAResource.rollback()
> XASession.close()
> throw RollbackException()
>
> and your problem is that the ActiveMQ session stays in limbo because it believes it's not closed, just because BTM called rollback on the XAResource it before
> closing the session.
>
> I'm sorry but that looks like an ActiveMQ bug to me. In their end() implementation, it appears that calling setXid(null) in a finally block would solve your issue
> but I don't know if that wouldn't have unwanted side effects.
>
> Another reason why I think it's their bug is because expecting the rollback to happen after the session is closed sounds illogical to me.
>
> I suggest your to report this problem to the ActiveMQ maintainers, but I'm open to discuss the issue furthermore if needed.
>
> 2011/9/9 Filipp Gunbin <[hidden email]>
>
>     Ludovic,
>     Thank you for the quick answer.
>    
>     Ludovic Orban <[hidden email]> writes:
>    
>     >
>     > 3. session close on DualSessionWrapper.
>     >
>     >     stateChanged() (called from DeferredReleaseSynchronization) does not actually close the original session
>     >
>     > What makes you believe that? When stateChanged() is called on DualSessionWrapper the latter immediately switches the state to CLOSED which triggers
>     > stateChanged() again to close the session, xaSession, producers and
>     > consumers.
>    
>     I've described it in details in failing commit scenario. In short, the
>     transactionId is not reset to null in TransactionContext and that makes
>     ActiveMQSession think it is still in transaction when it does
>     close(). And it registers its dispose method for later execution (which
>     never happens because rollback is already done) instead of immediate
>     operation.
>     That seems quite logical from the ActiveMQ's point of view. Maybe the
>     transactionId for a failed resource needs to be reset somewhere in BTM,
>     but that's just a rough guess.
>    
>     >
>     > It looks to me like both BTM and ActiveMQ are reacting the way they're supposed to when they face a connection failure. I fail to see where your problem is
>     > so could you please give more details about what you're observing and
>     > what you think is going wrong?
>    
>     The main problem is that unclosed session is retained in
>     ActiveMQConnection, it may receive messages (and does so), but no other
>     component will ever see it until connection reset (when all sessions are
>     forced to close). So the messages do not get consumed by the application
>     message listeners.
>    
>     I've described that in slightly more details in the first paragraphs of
>     the original post.
>    
>     Filipp.
>
>     >
>     > 2011/9/9 Filipp Gunbin <[hidden email]>
>     >
>     >     Hello,
>     >
>     >     I have a problem with BTM, I've tracked it down to a (rather clumsy) test case
>     >     which is attached with its Maven project.
>     >
>     >     I ran into this problem when I restarted broker while my app was running
>     >     and it stopped receiving messages. It turned out that a session was
>     >     still residing in ActiveMQConnection object after broker restart, it was
>     >     not registered anywhere in Bitronix session wrappers (only in the
>     >     connection which was cached) and that session received messages which
>     >     then could not be delivered to my app's message listeners.
>     >
>     >     In short, the description is:
>     >
>     >     The problem occurs when the broker stops while message listener in
>     >     Spring DefaultMessageListenerContainer hasn't committed yet. The session
>     >     is not actually removed from the ActiveMQConnection while its enclosing
>     >     JmsPooledConnection is considered closed and returned to the pool.
>     >
>     >     An ugly workaround is to force connection refresh - it makes the test
>     >     case pass.
>     >
>     >     Spring version: 3.0.5
>     >     Bitronix version: 2.1.1
>     >     ActiveMQ version: 5.4.2
>     >
>     >     I debugged both the successful transaction commit scenario and the
>     >     failing one, here is (roughly) what happens. Maybe it will help in some way.
>     >
>     >     1. Successful commit flow.
>     >
>     >     AbstractPollingMessageListenerContainer.doReceiveAndExecute()
>     >     BitronixTransactionManager.commit()
>     >     BitronixTransaction.commit()
>     >     post commit synchronizations
>     >     DeferredReleaseSynchronization sets state to IN_POOL for session
>     >     DualSessionWrapper.stateChanged() calls ActiveMQSession.close() and the
>     >     ActiveMQ session closes and removes itself from a connection
>     >
>     >     Everything OK here.
>     >
>     >     2. Failing commit scenario.
>     >
>     >     AbstractPollingMessageListenerContainer.doReceiveAndExecute()
>     >     BitronixTransactionManager.commit()
>     >     BitronixTransaction.commit()
>     >     BitronixTransaction.delistUnclosedResources() fails due to the
>     >     following:
>     >        BitronixTransaction.delistResource()
>     >        XAResourceManager.delist()
>     >        XAResourceHolderState.end() (here resource is marked as failed after
>     >        exception below)
>     >        TransactionContext.end()
>     >        TransactionContext.beforeEnd()
>     >        synchronizations
>     >        consumer.acknowledge() (here exception is thrown)
>     >     BitronixTransaction.rollback() - there's nothing to rollback (because
>     >     the resource is marked as failed)
>     >     post completion synchronizations
>     >     DeferredReleaseSynchronization sets state to IN_POOL for session
>     >     DualSessionWrapper.stateChanged() calls ActiveMQSession.close() and _it
>     >     registers its dispose on txContext.afterRollback_, because it thinks its
>     >     txContext is still in transaction. This is where session is not actually
>     >     closed. Rollback was not performed on a failed resource and
>     >     transactionId is still present in TransactionContext
>     >
>     >     So the main points for the failing scenario are:
>     >     1. consumer acknowledge causes the resource to be marked as failed
>     >     (because connection to the broker is not available)
>     >     2. rollback for the failed resource does nothing
>     >     3. session close on DualSessionWrapper.stateChanged() (called from
>     >     DeferredReleaseSynchronization) does not actually close the original
>     >     session
>     >
>     >     Thanks in advance for any help!
>     >
>     >     Filipp Gunbin
>     >     ---------------------------------------------------------------------
>     >     To unsubscribe from this list, please visit:
>     >
>     >        http://xircles.codehaus.org/manage_email
>    
>     ---------------------------------------------------------------------
>     To unsubscribe from this list, please visit:
>    
>        http://xircles.codehaus.org/manage_email

---------------------------------------------------------------------
To unsubscribe from this list, please visit:

    http://xircles.codehaus.org/manage_email


Reply | Threaded
Open this post in threaded view
|

Re: BTM + Spring + ActiveMQ - JMS session is not closed properly on broker connection failure

Ludovic Orban-2
See my answers inline.

2011/9/19 Filipp Gunbin <[hidden email]>
Do you mean that XAResource should stop thinking it's in a transaction
after its end() is called even if the exception is thrown somewhere in
the process of end()?

Yes, with the exception of XAER_PROTO under certain circumstances, there is no reason for an XAResource to believe it is still attached to a transactional context after end() has been called, even if an exception is thrown.

 
Then BTM will mark it as failed and will not call rollback() on it (as
it does now).

No, BTM will still try to rollback but will ignore if rollback fails or not as some XAResource implementations require that. But yes, the resource will be marked as failed.

 
(Anyway ActiveMQ's TransactionContext will not allow to call its
rollback() if the transaction is still in progress, there's a check at
the beginning of the method.)
ActiveMQSession will be closed correctly only when TransactionContext is
not in transaction.

And that check is perfectly sane and normal, assuming that XAER_PROTO is the specified error code.
 


If you confirm the above (that logic is OK from the BTM point of view)
I'll post this issue to the ActiveMQ mailing list.

Thanks,
Filipp


Please go ahead.


Ludovic
Reply | Threaded
Open this post in threaded view
|

Re: BTM + Spring + ActiveMQ - JMS session is not closed properly on broker connection failure

Filipp Gunbin
OK, thanks.

Where is a failed resource rolled back? I can't find that in code.

I see the following in BitronixTransaction.rollback():

if (!resourceHolderState.isFailed())
resourcesToRollback.add(resourceHolderState);

Filipp


Ludovic Orban <[hidden email]> writes:

> See my answers inline.
>
> 2011/9/19 Filipp Gunbin <[hidden email]>
>
>     Do you mean that XAResource should stop thinking it's in a transaction
>     after its end() is called even if the exception is thrown somewhere in
>     the process of end()?
>
> Yes, with the exception of XAER_PROTO under certain circumstances, there is no reason for an XAResource to believe it is still attached to a transactional context
> after end() has been called, even if an exception is thrown.
>
>  
>
>     Then BTM will mark it as failed and will not call rollback() on it (as
>     it does now).
>
> No, BTM will still try to rollback but will ignore if rollback fails or not as some XAResource implementations require that. But yes, the resource will be marked as
> failed.
>
>  
>
>     (Anyway ActiveMQ's TransactionContext will not allow to call its
>     rollback() if the transaction is still in progress, there's a check at
>     the beginning of the method.)
>     ActiveMQSession will be closed correctly only when TransactionContext is
>     not in transaction.
>
> And that check is perfectly sane and normal, assuming that XAER_PROTO is the specified error code.
>  
>
>     If you confirm the above (that logic is OK from the BTM point of view)
>     I'll post this issue to the ActiveMQ mailing list.
>    
>     Thanks,
>     Filipp
>
> Please go ahead.
>
> Ludovic

---------------------------------------------------------------------
To unsubscribe from this list, please visit:

    http://xircles.codehaus.org/manage_email


Reply | Threaded
Open this post in threaded view
|

Re: BTM + Spring + ActiveMQ - JMS session is not closed properly on broker connection failure

Ludovic Orban-2
Sorry, my mistake - my memory didn't serve me well this time.

I double-checked the code and indeed, when a resource is marked as failed, it is not rolled back.


2011/9/19 Filipp Gunbin <[hidden email]>
OK, thanks.

Where is a failed resource rolled back? I can't find that in code.

I see the following in BitronixTransaction.rollback():

if (!resourceHolderState.isFailed())
resourcesToRollback.add(resourceHolderState);

Filipp


Ludovic Orban <[hidden email]> writes:

> See my answers inline.
>
> 2011/9/19 Filipp Gunbin <[hidden email]>
>
>     Do you mean that XAResource should stop thinking it's in a transaction
>     after its end() is called even if the exception is thrown somewhere in
>     the process of end()?
>
> Yes, with the exception of XAER_PROTO under certain circumstances, there is no reason for an XAResource to believe it is still attached to a transactional context
> after end() has been called, even if an exception is thrown.
>
>  
>
>     Then BTM will mark it as failed and will not call rollback() on it (as
>     it does now).
>
> No, BTM will still try to rollback but will ignore if rollback fails or not as some XAResource implementations require that. But yes, the resource will be marked as
> failed.
>
>  
>
>     (Anyway ActiveMQ's TransactionContext will not allow to call its
>     rollback() if the transaction is still in progress, there's a check at
>     the beginning of the method.)
>     ActiveMQSession will be closed correctly only when TransactionContext is
>     not in transaction.
>
> And that check is perfectly sane and normal, assuming that XAER_PROTO is the specified error code.
>  
>
>     If you confirm the above (that logic is OK from the BTM point of view)
>     I'll post this issue to the ActiveMQ mailing list.
>
>     Thanks,
>     Filipp
>
> Please go ahead.
>
> Ludovic

---------------------------------------------------------------------
To unsubscribe from this list, please visit:

   http://xircles.codehaus.org/manage_email