tags:

views:

971

answers:

4

I have a .NET service that uses the ActiveMQ client. I have implemented a MessageListener with a transacted connection to consume the messages.

Occasionally, I get messages in a different order in which they were put onto the queue.

Was it wrong to use a MessageListner? Is there a way to preserve the message order?

FYI: There is one producer putting messages on the queue and one consumer pulling messages off the queue.

A: 

Why is message order important? A MessageListener shouldn't have to care.

If you need a correlation ID to match a response with a particular request, that's another matter. Is that what you mean?

duffymo
A message is sent to a server via queue and the server sends back responses to that message on another queue. I get 2 responses, first a message that says "Acknowledge" then one that says "Pass" (or Fail). The all have the same Correlation ID. Sometimes I get the "Acknowledge" message last.
Loki Stormbringer
bad design, IMO. The ACK sounds like it should be synchronous, nothing more than "We got your request and it will be processed." I'd have a synch processor like a servlet do that and put the request on the queue. Then it's just one req/res pair, and the correlation ID means something.
duffymo
+1  A: 

You shouldn't have to do anything to maintain the order; that's one of the things that a message queue does for you. I would think that if you have a single consumer listening to the queue, and it is processing messages out of order, then you have either found a bug or the messages aren't enqueued in the order you think they are.

Also, there's this question from the ActiveMQ FAQ that might help.

Edit: From reading the comments on duffymo's answer, it looks like you're overengineering a bit. In general, a message queue like ActiveMQ, MQ Series, joram, etc. have two characteristics: they deliver messages in the same order in which they are enqueued, and they guarantee message delivery. Sending a separate ACK message is redundant; it's a bit like committing a database transaction, then querying the same information back to double-check that the database actually stored it.

Having said that, is your server multithreaded? If so it may possible for it to enqueue the response before it enqueues the ACK.

Jason Day
A: 

Everything Jason just said. A few other things to be careful of. You are keeping the consumer open for lots of messages right? You're not creating a consumer for a few messages then closing it? Only closing a consumer causes messages associated with a consumer to be put back onto a queue which can break order.

Is it related to rollbacks? (Are you rolling back any transactions?).

Finally, you can always ensure order by using a Resequencer to reorder things for you.

James Strachan
+1  A: 

More Info: The server I call is third party and I have no control over what messages it sends. I do know, based on the message ID's that they are put on in the right order. Also, in this system there is a difference between ACK and Acknowledge. The ACK is received when my original message is put on the the "outbound" queue. I then monitor an "inbound" queue for responses. I usually get an "Acknowledge" followed by a "Pass" or a "Fail". The correlation ID for these messages is the message ID from the ACK.

I had originally used a message listener and responded to an OnMessge event. I abandoned this approach after realizing that, using this method, messages are delivered asynchronously and therefore in no particular order. So, I changed my code to poll using a timer (System.Threading.Timer) to call consumer.Receive() and get one message at a time. This works the way I want.

I open the consumer once when the service starts and I continuously poll for messages.

Loki Stormbringer