My application uses XA transaction for writing to db and publishing message out on MQ.
However Consumer application intermittently not able to find data in the database.
We are using
Weblogic 10.3 and oracle 10g
I thought as part of XA transaction, message will be sent out only when db commit is complete.
Any inputs on this will be appreciated..
Thanks.
The question is what data source are you using to execute xa transactions. If it is the emulated one this is expected, as you are only simulating xa.
Related
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.
We have what we believe is a fairly common XA use case:
read a message from an in-queue
write some data to a database
write a response message to an out-queue (which is different from the in-queue)
However we also need a way to handle internal errors and poison messages. The control flow we have in mind is something like this:
read the message from the in-queue
write to the database
if there's an exception roll back the database transaction
if there's no exception run commit phase1 on the database
if everything went fine (no rollback and commit phase1 ok) write a success message to the out-queue
if either commit phase1 on the database failed or there was an exception and the database transaction was rolled back write a failure message to the out-queue
commit the in-queue, the out-queue and the database (unless rolled by because of an exception)
Is this a good approach, should we do it differently? How can we do this with EJBs?
We're using EJB 3.1 on JBoss AS 7.2 / EAP 6.1, coding against Narayana directly is an option. The JDBC driver is ojdbc7-12.1.0.1 and the JMS RAR is MQ Series (don't know the version).
What you could do is to use the Java EE event mechanism to get a notification when your transaction fails and create a subsequent output message.
See
(EE7) http://docs.oracle.com/javaee/7/tutorial/doc/cdi-adv005.htm
(EE6) http://docs.oracle.com/javaee/6/tutorial/doc/gkhic.html
You need to use a new transaction to write to the out queue to avoid rolling back the message writing as well.
You will still have the message in the input queue which caused the exception, since the rollback will prevent the successfull consumption. You need to handle that separately, for example by the JMS provider.
I think I am not getting something right with JMS and JTA. I am running in a Java EE container with all CMTs. Here is what I am doing:
In an SLSB, write something to the database
From the same method of the SLSB, post a message to a JMS queue
An MDB in the same container listens to the JMS queue and picks up the message
The MDB reads the database
The problem is, the MDB does not see the changes made to the database in step 1.
I verified that steps 1 and 2 happen inside a single XA transaction, as expected. My expectation is that a second XA transaction would start at step 3, after the first XA has been committed. But it seems that the MDB receives the message before the XA transaction that posted the message has been committed.
Is my expectation wrong and what I am seeing is normal?
I am running under JBoss 6. The SLSB is local. Both the SLSB and the MDB are in the same application.
I found the problem! My JMS connection factory was not XA aware. I had looked up /XAConnectionFactory for my JMS connection factory. In spite of the name, that's the wrong resource to lookup for a regular app in JBoss. There is a java:/XAConnectionFactory too, which does not work either. The correct resource name is java:/JmsXA. I used it and everything is working just as expected.
Thanks to #strmqm for nudging me to the right direction.
I saw a conceptually similar problem in an app built w/ WebLogic 7. The DB commit from tx1 wasn't complete by the time that tx2 (initiated by a JMS send in tx1) tried to read it.
The trouble there was that our configuration involved a WLS 7 XA emulation layer with a non-XA db connection (to Oracle DB). This risk was part of that XA shortcut. Apparently if we'd gone w/ the true XA all the way to the DB, that hole would have closed. Never ended up testing that.
You say this is JBoss. Any chance that they've got some similar shim that bypasses the XA and gives this same surprising result?
I am currently integrating transaction management into my code.
I am trying to set it up against stored procedures that already exist.
The stored procedures have a commit at the end of them.
In my eclipse console, I can see the transaction management code being invoked
datasource.DataSourceTransactionManager Initiating transaction rollback
datasource.DataSourceTransactionManager Rolling back JDBC transaction on Connection [oracle.jdbc.driver.LogicalConnection#1544055]
datasource.DataSourceTransactionManager Releasing JDBC Connection [oracle.jdbc.driver.LogicalConnection#1544055] after transaction
But I can still see remains of the record that should have been rolled back in my database tables.
If we use spring transaction management, should we remove all commits from our stored procedures?
Thanks
Damien
I have a process which involves sending a JMS message.
The process is part of a transaction.
If a later part of the transaction fails, a part that is after a previous part that sent the message, I need to cancel the message.
One thought I had was to somehow set on the message that it is not to be picked up for a certain amount of time, and if I need to rollback, then I could go and cancel the message.
Not knowing messaging, I do not know if the idea is possible.
Or, is there a better idea?
Thanks
You can use JMS and JTA (Java Transaction API) together. When doing that, the sending of a JMS message or the consumption of a received message actually happens atomically as part of the transaction commit.
What does this mean? If the transaction fails or is rolled back, the "sent" message doesn't go out and any "received" messages aren't really consumed. All handled for you by your JMS and JTA provider.
You need to be using a JMS implementation that supports JTA. Sounds like you're already using transactions, so it might be a matter of doing some configuration to make it happen (waving hand vigorously...).
I've had experience using this (BEA WebLogic 7 w/ BEA WebLogic Integration). Worked as advertised -- "the outside world" saw no impact of JMS stuff I tried unless the transaction committed successfully.
Earlier versions of this linked to a Java page describing JMS/JTA integration generally. The page went stale and I don't see an equivalent replacement. This javadoc is for a JMS interface related to this capability.
What you have described is an XA transaction. This allows a transaction to scope across multiple layers i.e. JMS provider, DB or any other EIS. Most containers can be configured to use both non XA and none XA transaction so check your container settings!
For example if you are using JMS with XA transactions the following is possible.
Start Transaction
|
DB Insert
|
Send JMS Msg
|
More DB Inserts
|
Commit Transaction <- Only at this point will the database records be inserted and the JMS message sent.
XA Tranactions are only available in full Java EE containers so XA transactions are not available in Tomcat.
Good luck!
Karl