简体   繁体   中英

Standalone spring app XA transactions with IBM MQ and Oracle as resources

I am in the process of developing a stand alone Apache camel application (not running on a J2EE container). This apps needs to be capable of routing messages from an IBM MQ queue manager to an Oracle database in a distributed transaction. My google searches pretty much took me to a few places but none of those were able to give me some good clues about how to put everything together. This link below was the closest to what I need but unfortunately it is not cler enough to put me on the right path.

IBM MQManager as XA Transaction Manager with Spring-jms and Spring-tx

Thank you in advance for your inputs.

You will need to use a JTA TransactionManager, but since not being in a j2ee container i would sugest to use Atomikos.

https://github.com/camelinaction/camelinaction/tree/master/chapter9/xa

My route which is working with IBM MQ -> Oracle Database, in an J2EE yes but still should be working with Atomikos setup. I would say this isn't the proper way to to it, but it's the only way I managed to get it working - working well enough for my use case.

from(inQueue)
    .transacted()
    .setHeader("storeData", constant(false))
    .to("direct:a")
    .choice().when(header("storeData").isEqualTo(false)) // if this is true the database calls are 'successful'
    .log("Sending message to errorQueue")
    .to(errorQueue)
;

StoreDataBean storeDataBean = new StoreDataBean();
from("direct:a")
    .onException(Exception.class).handled(false).log("Rollbacking database changes").markRollbackOnlyLast().end()
    .transacted("PROPAGATION_REQUIRES_NEW")
    .bean(storeDataBean) //storeData sets the header storeData to true if no SQLException or other exceptions are thrown
    .end()
;

The commit are handled by the transaction manager, so if I actually get an error with the database commit, it should rollback the message. Next problem that I have had with rollbacking messages is that I can't set the deadLetterQueue, as you can with ActiveMQ. So it rolls back to the incoming queue. Therefore I actually handle the database transaction as I do, it is in a new transaction, which is rollbacked in case of a normal SQLException when calling the database.

I wished this worked:

from(inQueue)
    .onException(Exception.class).to(errorQueue).markRollbackOnly().end()
    .bean(storeDataBean)
    .end()

I have posted about this in the community forums but no answers at all.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM