Author |
Message
|
jkfriends |
Posted: Wed Oct 14, 2009 12:45 pm Post subject: MQ transaction support |
|
|
Novice
Joined: 09 Oct 2009 Posts: 20
|
Hi, I got my MQ WebSprhere Client V6 configured properly on my PC and I'm using C# (.NET) APIs to read a message from a specified queue/queue manager.
Here is the code that I use to read a message and it is working correctly:
Code: |
MQGetMessageOptions gmo = new MQGetMessageOptions();
gmo.Options = MQC.MQGMO_FAIL_IF_QUIESCING | MQC.MQGMO_WAIT;
gmo.WaitInterval = MQC.MQWI_UNLIMITED;
MQMessage message = new MQMessage();
//wait for message
queue.Get(message, gmo); |
Now the question is that how do I do the read with a transaction support? Here is my requirement:
1) Begin a MQ transaction.
2) Read a message (XML) from the defined queue name.
3) Once I get a message, I submit the message into another process (WCF service 1-way) to do the actual processing of the message.
4) If the WCF service call fails, I want to move the read message into another queue on the side and then I want to commit the MQ transaction. If sending to another queue fails for some reason, I want to rollback or abort the MQ transaction so that the orignally read message is put back into the source queue.
5) If the WCF service call succeeds, commit the MQ transaction.
How do I achieve this functionality using C# using WebSphere APIs? Any code snippets would be appreciated.
Thanks, JK
Last edited by jkfriends on Wed Oct 14, 2009 12:47 pm; edited 1 time in total |
|
Back to top |
|
 |
mqjeff |
Posted: Wed Oct 14, 2009 12:46 pm Post subject: |
|
|
Grand Master
Joined: 25 Jun 2008 Posts: 17447
|
|
Back to top |
|
 |
jkfriends |
Posted: Wed Oct 14, 2009 1:05 pm Post subject: Thanks! |
|
|
Novice
Joined: 09 Oct 2009 Posts: 20
|
Thank you mqjeff for a quick response. I searched around of this option MQC.MQPMO_SYNCPOINT and found some examples. Here is my question on this.
If I use UNLIMITED wait interval option along with SYNCPOINT option and my transaction scope (from C# TransactionScope object) with default of 60 seconds time out, what happens if there is no message to read from the queue for 10 minutes? I assume that the transaction scope will timeout and exit? What happens to the Get function within the transaction scope? How does it handled? Could you please explain?
Thanks. |
|
Back to top |
|
 |
Vitor |
Posted: Wed Oct 14, 2009 2:36 pm Post subject: Re: Thanks! |
|
|
 Grand High Poobah
Joined: 11 Nov 2005 Posts: 26093 Location: Texas, USA
|
jkfriends wrote: |
If I use UNLIMITED wait interval option along with SYNCPOINT option and my transaction scope (from C# TransactionScope object) with default of 60 seconds time out, what happens if there is no message to read from the queue for 10 minutes? |
Nothing - if you set wait to unlimited, the time interval is ignored. If you do use the time interval, if no message is available then a 2033 reason code is returned to the application. This has nothing to do with transaction control.[/quote]
jkfriends wrote: |
I assume that the transaction scope will timeout and exit? |
No. The transaction does what you code it to do. See my comments above regarding the difference between message wait and transactional scope.
jkfriends wrote: |
What happens to the Get function within the transaction scope? |
Same as the put. Note that MQPMO_SYNCPOINT is not the same as MQGMO_SYNCPOINT.
jkfriends wrote: |
How does it handled? |
However you see fit.
jkfriends wrote: |
Could you please explain? |
Not as well as the Application Programming Guide does. This explains the options available to your application.
Also be aware that what's being described here is a single-phase commit within the queue manager, not a two-phase commit syncronised with a database or other external resource. _________________ Honesty is the best policy.
Insanity is the best defence. |
|
Back to top |
|
 |
jkfriends |
Posted: Thu Oct 15, 2009 4:36 am Post subject: |
|
|
Novice
Joined: 09 Oct 2009 Posts: 20
|
Thanks Vitor. I got the concept and I'm almost done with my C# prototype. I do use MQGMO_SYNCPOINT option while doing the get within a transaction scope (.NET) with wait interval of 3 seconds. If I don't get a message, I get CompCode=2, Reason=2033 (no message found) and I consider that exception as normal and move on with the next step. However I see an exception text written to my Output window (A first chance exception of type 'IBM.WMQ.MQException' occured in amqmdnet.dll). Also an entry is logged in the event log. If I do this get in a forever loop, I would fill up the event log quite quickly.
So what do I do to not to do this when this exception occurs? Is there any option that I can pass that would avoid this?
Thanks. |
|
Back to top |
|
 |
Vitor |
Posted: Thu Oct 15, 2009 6:32 am Post subject: |
|
|
 Grand High Poobah
Joined: 11 Nov 2005 Posts: 26093 Location: Texas, USA
|
jkfriends wrote: |
So what do I do to not to do this when this exception occurs? Is there any option that I can pass that would avoid this?
|
No. WMQ will always throw a 2033 code when there's no message available. You're correct in considering this a "normal" error; the traditional model for most applications is to read a queue until you get a 2033.
All you need is relevant code in your app so that it considers the application normal just like you do.  _________________ Honesty is the best policy.
Insanity is the best defence. |
|
Back to top |
|
 |
fjb_saper |
Posted: Thu Oct 15, 2009 6:34 am Post subject: |
|
|
 Grand High Poobah
Joined: 18 Nov 2003 Posts: 20756 Location: LI,NY
|
Vitor wrote: |
jkfriends wrote: |
So what do I do to not to do this when this exception occurs? Is there any option that I can pass that would avoid this?
|
No. WMQ will always throw a 2033 code when there's no message available. You're correct in considering this a "normal" error; the traditional model for most applications is to read a queue until you get a 2033.
All you need is relevant code in your app so that it considers the application normal just like you do.  |
If the messages are sparse enough, you could also think about writing a triggered app...  _________________ MQ & Broker admin |
|
Back to top |
|
 |
Vitor |
Posted: Thu Oct 15, 2009 6:40 am Post subject: |
|
|
 Grand High Poobah
Joined: 11 Nov 2005 Posts: 26093 Location: Texas, USA
|
fjb_saper wrote: |
Vitor wrote: |
jkfriends wrote: |
So what do I do to not to do this when this exception occurs? Is there any option that I can pass that would avoid this?
|
No. WMQ will always throw a 2033 code when there's no message available. You're correct in considering this a "normal" error; the traditional model for most applications is to read a queue until you get a 2033.
All you need is relevant code in your app so that it considers the application normal just like you do.  |
If the messages are sparse enough, you could also think about writing a triggered app...  |
Very true...  _________________ Honesty is the best policy.
Insanity is the best defence. |
|
Back to top |
|
 |
jkfriends |
Posted: Thu Oct 15, 2009 9:13 am Post subject: |
|
|
Novice
Joined: 09 Oct 2009 Posts: 20
|
Got it working now. Instead of mixing TransactionScope from .NET with MQ APIs, I decided to ignore .NET transaction scope completely.
Here is the logic that I implemented in C# using purely MQ APIs only and it seems to be working fine.
Code: |
While Forever
Do MQ get with UNLIMITED + GET_SYNCPOINT
Process the messsage
If something goes wrong with the process,
I move the message to different error queue with PUT_SYNCPOINT
Endif
Commit using MQQueueManager (so that both GET and PUT are under same transaction)
End While |
With this approach, I don't get Umpteen number of exceptions thrown since I use unlimited wait inteval.
My question is that if I use GET_SYNCPOINT and UNLIMITED wait interval together in GET function, will that keep a long running MQ transaction scope until it find a message? Or the transaction actually gets started only after successfully getting a message from a queue?
Thanks. |
|
Back to top |
|
 |
Vitor |
Posted: Thu Oct 15, 2009 9:44 am Post subject: |
|
|
 Grand High Poobah
Joined: 11 Nov 2005 Posts: 26093 Location: Texas, USA
|
jkfriends wrote: |
With this approach, I don't get Umpteen number of exceptions thrown since I use unlimited wait inteval. |
But you will get other problems with this. For instance, how do you trigger the application to stop and disconnect from the queue manager? If you just cancel the app while the get is waiting on the queue, you'll leave the handle open on the queue manager.
jkfriends wrote: |
My question is that if I use GET_SYNCPOINT and UNLIMITED wait interval together in GET function, will that keep a long running MQ transaction scope until it find a message? Or the transaction actually gets started only after successfully getting a message from a queue? |
It starts from the previous commit unless an explicit begin has been issued.
My question is why are you using transactions at all. The transaction is intended to roll messages back on or off of queues in the event of a problem; you're moving the message to an error queue explicitly in the event of an error and committing unconditionally.
If you're determined to use transactions, you'd be better off issuing a rollback in the event of an error and checking backout count on the get. _________________ Honesty is the best policy.
Insanity is the best defence. |
|
Back to top |
|
 |
jkfriends |
Posted: Thu Oct 15, 2009 9:54 am Post subject: |
|
|
Novice
Joined: 09 Oct 2009 Posts: 20
|
I did not explain the whole picture. The code that I posted above is one part of the puzzle. It will be a Windows Service.
Code: |
OnStart()
Open MQ resources & others
OnMessagePump()
Logic that I posted above
OnStop()
Release MQ resources & others |
As I get a message from the MQ, I want to make sure it is properly processed. The actual processing happens on a web service to a different server. This windows service would simply wait until the web service returns back successfully. If so it would commit the MQ transaction (using qmgr.Commit()). If not, move the message to the error queue and then do the MQ commit. If this Windows Service crashes after getting a message from the queue and before processing the message, I would want to put the message back to the listen queue which will happen if I use GET_SYNCPOINT option automatically and acutally it works.
So in summary I use GET_SYNCPOINT option, qmgr.Commit() and qmgr.Backout() if writing to the error queue fails. In that case, I would stop the windows service after rolling back MQ get message. |
|
Back to top |
|
 |
jkfriends |
Posted: Thu Oct 15, 2009 9:58 am Post subject: |
|
|
Novice
Joined: 09 Oct 2009 Posts: 20
|
Regarding explicit Begin() command throws an exception 2012 (MQ environment error or something). So how do I use the Begin() command?
To my previous question (if I use GET_SYNCPOINT + UNLIMITED wait interval), will the transaction actually start after getting a message from the queue? |
|
Back to top |
|
 |
mqjeff |
Posted: Thu Oct 15, 2009 10:08 am Post subject: |
|
|
Grand Master
Joined: 25 Jun 2008 Posts: 17447
|
You don't use Begin unless you use XA. |
|
Back to top |
|
 |
bruce2359 |
Posted: Thu Oct 15, 2009 10:51 am Post subject: |
|
|
 Poobah
Joined: 05 Jan 2008 Posts: 9471 Location: US: west coast, almost. Otherwise, enroute.
|
Quote: |
To my previous question (if I use GET_SYNCPOINT + UNLIMITED wait interval), will the transaction actually start after getting a message from the queue? |
GET_SYNCPOINT will ensure that the MQGET will be done within the Unit of Work (the transaction). Do not wait unlimited, as this might create a never-ending Unit of Work.
2033 is not an error; rather, it is like a traditional end-of-file - just no more data to process.
A transaction effectively starts when the first resource is changed, and ends with an MQCMIT or MQBACK. By definition, a transaction is a short-lived event - thus no wait unlimited. _________________ I like deadlines. I like to wave as they pass by.
ב''ה
Lex Orandi, Lex Credendi, Lex Vivendi. As we Worship, So we Believe, So we Live. |
|
Back to top |
|
 |
bruce2359 |
Posted: Thu Oct 15, 2009 10:52 am Post subject: |
|
|
 Poobah
Joined: 05 Jan 2008 Posts: 9471 Location: US: west coast, almost. Otherwise, enroute.
|
Quote: |
You don't use Begin unless you use XA. |
Which means that you are changing resources of both the qmgr AND the resources of another resource manager (DB2, for example); and MQCMIT/MQBACK will complete the transaction. _________________ I like deadlines. I like to wave as they pass by.
ב''ה
Lex Orandi, Lex Credendi, Lex Vivendi. As we Worship, So we Believe, So we Live. |
|
Back to top |
|
 |
|