tags:

views:

86

answers:

2

I am working on a multithreaded JMS receiver and publisher code. XML message is received from a Queue, stored procedures(takes 70 sec to execute) are called and response is send to Topic within 90 sec. I need to handle a condition when broker is down. i.e. a condition in which messages are received from Queue and are being processed in java, in the mean time both Queue and Topic will be down. Then how to handle those messages which are not on queue and not send to topic but are in java memory? Different options available:

1.To use CLIENT_ACKNOWLEDGE 2.To separate publisher code from receiver code. 3.To have error utility which will take messages from log and process them and send to Topic(least preferred)

Please suggest me the right option

+2  A: 

Use a transacted session. Consume the message and send the response under a single unit of work and explicitly call COMMIT after sending the response. Then if the broker dies while the transaction is outstanding the input message will be rolled back. If you include the DB update in a two-phase coordinated transaction then it too can be rolled back of the broker goes down. This requires the consumer and responder to be within the same thread because JMS scopes sessions per thread, but you can have several threads running sessions in parallel.

Be aware that keeping many transactions open for 90 seconds might require some tuning at the broker side.

T.Rob
I believe that if the session was transacted, the acknowledgment mode (e.g. CLIENT_ACKNOWLEDGE) is ignored :)
Ahmad
Yeah, I'm thinking with my WMQ hat on. We generally set CLIENT_ACKNOWLEDGE in the managed object because it as to be set to *something* and this clues in anyone reading it that the code should explicitly commit. However, from a JMS perspective it doesn't do anything. I've edited that out of my response. +1 for the good catch.
T.Rob
Thanks alot! if instead of connection.createSession(false, javax.jms.Session.CLIENT_ACKNOWLEDGE) , I will use connection.createSession(true, javax.jms.Session.CLIENT_ACKNOWLEDGE); then session is transacted and acknowledgement mode is ignored. After sending the response to Topic I will commit() the session. My Question is that if session is rolled back in case of some exception(like broker down and response cannot be send to Topic) then that message still exists on queue i.e when broker is back after 10 mins then that message is still on queue?
Jyoti
Yes. The message is not deleted until the COMMIT call succeeds. If there is a failure of the broker or the app, the message will be rolled back (possibly not until TCP times out and tells the broker the app is gone though). While the message is under syncpoint awaiting COMMIT, no other consumer will see that instance of the message. After it is rolled back, any consumer on that queue is eligible to receive it again.
T.Rob
Thanks! But I am facing a new problem. Because of some exception in transaction the massage is rolled back and re delivered. They are rolled back again and again and continue until I kill the program. This thing I want to avoid. Can I limit the number of re delivery?
Jyoti
OK, so set the queue attributes BOQNAME and BOQTHRESH to take care of this. But ask it in a new question and I'll be able to post links and a full response. It will also make it easier for the next person to find the answer and make the Wiki here work better.
T.Rob
A: 

One solution is to use db for intermediate stored procedure. So the steps would be:

1. Consume Message from Queue and store into db and use Client_Acknowledge.
2. Run stored procedures on the consumed message.
3. Once the procedure is over, send message from db to the topic.
4. Delete message once acknowledgement is recieved.

If queue and topic goes down in between, you just need to send message again when acknowledgement is not recieved from topic.

Well I am not sure whether this is the best alternative and want to see how community responds on this question.

Ankit
what is db? database ?
Jyoti
yes... I mean store message in database.
Ankit
storing message in database in not feasible, need to call stored procedure from java only (some database constraints)
Jyoti