Websphere MQ topics - are they strictly ordered? - java

Are messages received on a Websphere MQ topic that you are subscribed to strictly ordered?
In other words, in similar fashion to a queue, given that your connection is maintained are you guaranteed to receive the topic messages in the same order as they were sent?

As per JMS specs
JMS defines that messages sent by a session to a destination must be received
in the order in which they were sent. This defines a partial ordering
constraint on a session’s input message stream.
JMS does not define order of message receipt across destinations or across
a destination’s messages sent from multiple sessions. This aspect of a
session’s input message stream order is timing-dependent. It is not under
application control.
Also
Although clients loosely view the messages they produce within a session
as forming a serial stream of sent messages, the total ordering of this stream
is not significant. The only ordering that is visible to receiving clients is
the order of messages a session sends to a particular destination.
Several things can affect this order like message priority,
persistent/non persistent etc.
So to answer your question it is not really JMS provider specific what order messages are received. They will be received in the same order they were sent with above information. The order in which messages are delivered to the server however will be constrained by limitations like message priority, persistent/non persistent etc.

Related

Java ActiveMQ: How to send a message from the client to the server

I've seen a lot of code and examples on how to send a message from the server/producer to the client, but I'm lost as to how to send a message from the client to the server. Does it follow the same format?
For example, say my server has 5 topics: A, B, C, D, E. My client is listening to only topic C.
So my server creates a queue and sends messages to subscribers/clients.
My client gets messages that are on topic C. It performs some computation, and I want to send a message back to the publisher (say an int for example). What are the required steps?
Do I need to set a destination/topic for the producer to listen to?
Does my producer automatically listen to all clients (once they connect)?
I think you may need to do a bit of reading around the various communication models available e.g. this on JMS Models.
You have started by using Topics, but your statements hint at a One-to-One relationship between sender and receiver. For this queues may be more appropriate. Topics are generally for publishing information where the publisher doesn't know (nor care) about the subscribers - and there can be many.
On the other hand Queuing is intended to deliver to a specific target. With this you can still do "fire-and-forget" (where the sender puts the message out to a queue and doesn't wait for the expected consumer to process it)
Or you can add response handling to that - essentially by adding a "parallel" response queue (where the initial sender will processes the response messages back from the consumer - usually in a different thread).
ActiveMQ and JMS have "reply-to" functionality - where the sender indicates on send the queue name where it wants to see responses come back to - and the consumer complies with that. The reply-to queue can be fixed or a temporary one that the sender creates up-front.
All depends on what model you are going for.

JMS previous message acknowledgement

I am trying to solve the following case:
I am consuming messages, but take an outage in a system I am depending on for proper message processing (say a Database for example)
I am using CLIENT_ACKNOWLEDGE, and only calling the .acknowledge() method when no exception is thrown.
This works fine when I throw an exception, messages are not acknowledged, and I can see the unacknowledged queue building up. However, these messages have all already been delivered to the consumer.
Suppose now the Database comes back online, and any new message is processed successfully. So I call .acknowledge on them. I read that calling .acknowledge() acknowledges not only that message, but also all previously received messages in the consumer.
This is not what I want! I need these previously unacknowledged messages to be redelivered / retried. I would like to keep them on the queue and let JMS handle the retry, since maintaining a Collection in the consumer of "messages to be retried" might put at risk losing those messages ( since .acknowledge already ack'ed all of them + say the hardware failed).
Is there a way to explicitly acknowledge specific messages and not have this "acknowledge all prior messages" behavior?
Acknowledging specific message is not defined by JMS specification. Hence some JMS implementers provide per messaging acknowledging and some don't. You will need to check your JMS provider documentation.
Message queues generally will have an option on how the messages are delivered to a client, either First in first out (FIFO) or Priority based. Choose FIFO option so that all messages are delivered in the same order they came into a queue. When database goes offline and comes back, call recover method to redeliver all messages in the same order again.
You need to call recover on your session after the failure to restart message delivery from the first unacked message. From the JMS 1.1 spec section 4.4.11
When CLIENT_ACKNOWLEDGE mode is used, a client may build up a large
number of unacknowledged messages while attempting to process them. A
JMS provider should provide administrators with a way to limit client
over-run so that clients are not driven to resource exhaustion and
ensuing failure when some resource they are using is temporarily
blocked.
A session’s recover method is used to stop a session and restart it
with its first unacknowledged message. In effect, the session’s series
of delivered messages is reset to the point after its last
acknowledged message. The messages it now delivers may be different
from those that were originally delivered due to message expiration
and the arrival of higher-priority messages.

JMS architecture for group broadcasting

I want to build a broadcasting system. It consists of several groups. Each group has one User who can broadcast a message to the other members of the same group. What is the appropriate JMS architecture for this kind of system?
Should I use a topic with durable subscription? I don't know much about pub/sub messaging style, can topic have multiple subscription? If so, then each subscription represents a group in the broadcasting system. If not, should I use a queue whereas each message has a header specifying the group and then use a JMS selector to filter the message so that each member receive only messages from groups he's in?
Also, I am thinking of persisting the messages after consumption. I decided to make each message to expire after one hour, and each member should check the database for every message he misses. But, how can I fire an action upon message expiration?
Topics can be used... Topics can have multiple subscribers. Each group can use a different topic. The user can send message to that topic and all the subscribers would receive it.
The durable subscribers are required only if the subscribers can go offline for sometime and the messages for the subscriber shouldn't be lost.
Queue doesn't suite well in one-to-many scenarios. But if you have a pre-defined set of receivers you can use a queue for each one of them and route messages to that. But this is a overhead to route the messages to the receiver's queue. JMS selector idea you have suggested would work but for a queue only one client can receive a message. In topics it distributed to all the clients interested in that topic.
Normally one would persist data to database and not the message itself. So you can persist to database and then create the message for delivery.

JMS queue message receive order

I am adding two JMS messages in the same destination sequentially. Will both of these messages be received in the same order in which I have added them or is there a chance for reverse ordering, that is, which ever the message is received first in the destination will be retrieved first.
I am adding into a destination as:
producer.send(Msg1);
producer.send(Msg2);
Msg1 and Msg2 will be added sequentially in all the cases (like network failures and latency. etc.)?
Message ordering is not guaranteed (and not mandated by the specification) and Total JMS Message ordering explains the details of why. Also see the Stack Overflow post How to handle order of messages in JMS?.
As per JMS2 specs
JMS defines that messages sent by a session to a destination must be received
in the order in which they were sent. This defines a partial ordering
constraint on a session’s input message stream.
JMS does not define order of message receipt across destinations or across
a destination’s messages sent from multiple sessions. This aspect of a
session’s input message stream order is timing-dependent. It is not under
application control.
Also
Although clients loosely view the messages they produce within a session
as forming a serial stream of sent messages, the total ordering of this stream
is not significant. The only ordering that is visible to receiving clients is
the order of messages a session sends to a particular destination.
Several things can affect this order like message priority,
persistent/non persistent etc.
So to answer your question messages will be received in the same order they were sent with above information. The order in which messages are delivered to the server however will be constrained by limitations like message priority, persistent/non persistent etc.

do message queues provide transactional support?

Say I load messages in a queue from multiple nodes.
Then, one or many nodes are pulling messages from the queue.
Is it possible (or is this normal usage?) that the queue guarantees to not hand out a message to more than one server/node?
And does that server/node have to tell the queue it has completed the operation and the queue and delete the message?
A message queuing system that did not guarantee to hand out a given message to just one recipient would not be worth the using. Some message queue systems have transactional controls. In that case, if a message is collected by one receiver as part of a transaction, but the receiver does not then commit the transaction (and the message queue can identify that the original recipient is no longer available), then it would be reissued. However, the message would not be made available to two processes concurrently.
What messaging/queuing technology are you using ? AMQP can certainly guarantee this behaviour (amongst many others, including pub/sub models)
If you want this in Java - then a JMS compliant messaging system will do what you want - and most messaging systems have a JMS client. You can Use Spring's JmsTemplate for real ease of use too.
With JMS - a message from a Queue will only be consumed by one and only one client - and once it is consumed (acknowledged) - it will be removed from the messaging system. Also when you publish a message using JMS - if its persistent - it will be sent synchronously, and the send() method won't return until the message is stored on the broker's disk - this is important - if you don't want to run the risk of loosing messages in the event of failure.

Categories