7 Replies Latest reply on Dec 14, 2007 3:35 PM by marklittle

    Simple way to achieve rollback-only recovery?

    ydzsidemiik

      I wrote a resource adapter at the <transaction-support>XATransaction</transaction-support> level. My XAResource is not serializable, so when my application server crashes, I get the usual recovery warnings about non-serializable XAResources.

      Right now my implementation of recover() returns Xid[0]. I do not really want to implement anything fancier, as the underlying messaging resource is not actually XA; I just tie the request-response cycle into the global transaction to roll back if the response is not received. I understand that this results in at-least-once delivery semantics, which is fine.

      I am looking for the easiest way to simply roll back any incomplete transactions when the application server resumes. Can it be done through configuration? Will I have to write code, and if so are there any examples available?

      Thanks!

        • 1. Re: Simple way to achieve rollback-only recovery?
          marklittle

          You want to force rollback of transactions for which the recovery subsystem can't find a new XAResource?

          • 2. Re: Simple way to achieve rollback-only recovery?
            ydzsidemiik

            Yes, that's a good way to put it. Is it possible? I am not an expert in XA so I may be missing something fundamental, but it seems reasonable enough.

            • 3. Re: Simple way to achieve rollback-only recovery?
              marklittle

              Good. That's what I thought. ;-)

              So you're basically asking the transaction system to no longer act as a transaction system and roll back transactions. You're breaking the rules. I'm sorry to say that we don't do that and would certainly not encourage you to do that. It's definitely not "reasonable" to do that ;-)

              If you are getting these warnings then the transaction manager is telling you about them for a reason: there were crashes and the transaction has not completed. You ignore them at your risk. If you were to rollback the entries regardless, then you could end up with data corruption and/or heuristic outcomes. Neither of which are good.

              If you explain why you can't let the transaction manager do the right thing, it may help us to help you.

              • 4. Re: Simple way to achieve rollback-only recovery?
                ydzsidemiik

                Well, my resource adapter implements a messaging protocol which is non-transactional. The RA is called from a JMS MDB, so that it participates in the container initiated MDB transaction. The MDB calls the RA to send the message to the destination. The RA sends the message and then waits for a response. If it does not receive one, it votes rollback at prepare time, which causes the JMS Queue driving the MDB to also rollback and the delivery to be retried. This is the extent of the RA's participation in the XA protocol.

                It seemed like a good idea at the time. In retrospect, attempting to implement a non-transactional protocol using a transactional resource adapter was a poor choice and has led to all sorts of completely unnecessary problems, but that is neither here nor there.

                It is clear from this that (1) recovery is un-necessary for this resource since there is nothing to recover and (2) the heuristic outcome boils down to duplicate deliveries to the destination, which we have to make peace with since the messaging protocol is non-transactional (nor does it have client supplied unique message IDs). If I could get the resources other than my RA participating in the transaction to all roll back, I would be satisfied with the integrity of the transaction as a whole.

                Thanks for your time by the way. I know this probably makes your head hurt. I know it does mine ;)

                • 5. Re: Simple way to achieve rollback-only recovery?
                  marklittle

                  If your resource is only one-phase aware (either it commits or rolls back, and there is no prepare stage), then you could add it to the transaction and use the Last Resource Commit Optimization. There will never be any recover on behalf of that resource because it's not a true XA participant in that case.

                  • 6. Re: Simple way to achieve rollback-only recovery?
                    ydzsidemiik

                    I already have JBossTS driving my database as a last resource. Though Postgres supposedly supports XA, I had terrible problems when trying to use an xa-datasource with it; hails of HeuristicMixedExceptions while under load.

                    What would happen if I provided a serializable XAResource that always returned Xid[0]? What about if recovery was disabled entirely -- could it lead to loss of messages from queues, or are they guaranteed to be redelivered unless the tx commits? (I guess that's one for the JBM guys.) What about if I deleted the ObjectStore?

                    I appreciate that these questions step into "helping the user shoot themselves in the foot" territory, through which you may not be eager to stroll. In any case, I've learned something.

                    • 7. Re: Simple way to achieve rollback-only recovery?
                      marklittle

                      I wouldn't recommend disabling recovery. If you go down that route you may as well look at the wiki to see how you can enlist multiple one-phase aware resources in the transaction: neither approach gives you the benefits of transactions!

                      If you want the benefits of transactions then you need to get an XAResource implementation that works.

                      If you are willing to run the risk, then multiple 1PC resources should work for you. Or you could go down the Serializable XAResource route, return null from recover, and make sure that commit always succeeds.