Message ordering is important to some asynchronous messaging
applications; that is, it is important to consume messages in the
same order that the producer sends them. If this type of message ordering
is important to your application, your design must take it into account.
For example, a messaging application that processes seat
reservations might have producer components and a consumer component.
A producer component sends a message to the consumer component when
a customer reserves a seat. If the customer cancels the reservation
then the producer (or possibly a different producer) sends a second
message. Typically, the consumer component must process the first
message (which reserves the seat) before it processes the second message
(which cancels the reservation).
Some applications use a synchronous (request-response)
pattern where the producer waits for a response to each message before
it sends the next message. In this type of application, the consumer
controls the order in which it receives the messages and can ensure
that this is the same order as the producer or producers send them.
Other applications use an asynchronous (fire and forget) pattern where
the producer sends messages without waiting for responses. Even for
this type of application, order is usually preserved; that is, a consumer
can expect to receive messages in the same order as the producer or
producers send them, especially when there is a significant time between
sending consecutive messages. However your design must consider factors
that can disrupt this order.
The order of messages is disrupted if your application
sends messages with different priorities (higher priority messages
can overtake lower priority messages) or if your application explicitly
receives a message other than the first by specifying message selectors.
Parallel processing and error or exception processing can also affect
message ordering.
Parallel processing
- Multiple destinations
- When a producer sends a message to one destination and then sends
a second message to a different destination, it is possible that the
second message arrives at its destination before the first message
arrives at its destination. This can happen even if the producer sends
both messages within the same transaction (the transaction ensures
that either both sends fail or both complete; it does not ensure the
delivery order). If this is a problem for your application then avoid
using more than one destination for that application.
- Multiple producers
- When one producer sends a message to a destination and then a
second producer sends a second message to the same destination, it
is possible that the second message arrives at the destination before
the first message. This can happen even if the second producer synchronizes
with the first producer, for example by waiting for a signal from
the first producer before sending its message (the second message).
It can also happen even if the producers are transactional (the fact
that a transaction is complete does not mean that the message or messages
are at the destination - service integration can complete a transaction
first and deliver the message or messages later). If this is a problem
for your application then avoid using more than one producer for that
application. Similarly, avoid using a single producer which runs multiple
parallel threads.
- Multiple consumers
- When two messages arrive at a queue-type destination where there
are multiple consumers, it is possible that one consumer receives
the first message and another receives the second. If the consumers
can run in parallel then the consumer which receives the second message
might process it before the consumer which receives the first message.
Also, if one consumer receives a message transactionally and then
rolls-back the transaction, the message returns to the destination
where another consumer can receive it; meanwhile, that other consumer
might already have received and processed other (later) messages.
If either of these are a problem for your application then avoid
using more than one consumer for that application. Similarly, do not
allow multiple concurrent message-driven bean (MDB) invocations per
endpoint (see Configuring MDB throttling for the default messaging provider). Alternatively,
consider using strict message ordering, see Strict message ordering for bus destinations.
- Clustering and partitioned destinations
- When a queue-type destination is assigned to a cluster bus member
with more than one messaging engine then each messaging engine contains
a partition of the destination (that is, one of the destination queue
points); service integration can deliver different messages for that
destination to different partitions. This queue-type destination
configuration can provide advanced availability, scalability, and
load balancing but it is not usually suitable for applications where
message ordering is important. Service integration does not guarantee
the ordering of messages sent to different partitions of the same
destination. Also, a messaging engine can fail while there are messages
on the destination partition that it contains; these messages are
not available to consumers until the messaging engine restarts. However,
service integration can continue delivering newer messages to other
partitions (in other messaging engines) and consumers can receive
and process these newer messages before the older messages on the
failed messaging engine partition. Workload sharing with queue destinations gives more detail on this type of configuration,
and also explains how you can use the Message affinity option which
can help maintain message ordering between a single producer and a
single consumer in a cluster (though not if the cluster is in a different
service integration bus).
- Publish and subscribe
- For publish-subscribe messaging, service integration does not
guarantee the ordering of messages received by different instances
of a subscription, including separate instances of a durable subscription
created with the Share Durable Subscriptions property set to permit
sharing.
Errors and exception conditions
- Quality of service
- The quality of service for a message determines how error and
exception conditions can affect the delivery of the message (see Message reliability levels - JMS delivery mode and service integration quality of service. Depending on
the quality of service, an error or exception condition can cause
service integration to deliver the message reliably (exactly once)
or less reliably (more than once, or not at all). For example, with
the express nonpersistent quality of service, it is possible for sequences
of messages to be re-delivered after a failure; however, their underlying
order is always maintained so that messages might arrive in the sequence:
1, 2, 3, 2, 3, 4. More generally, service integration does not guarantee
the ordering of different messages sent with different qualities of
service. If this is a problem for your application then be sure to
select an appropriate quality of service and avoid mixing different
qualities of service for messages to the same destination.
- Exception destinations
- Under certain failure scenarios, service integration can deliver
a message to an exception destination or deliver a message to a destination
and subsequently transfer the message to an exception destination.
Service integration does not guarantee the ordering of messages it
sends to or transfers to an exception destination. If this is a problem
for your application then you can configure the destination so that
it does not use an exception destination (see Exception destinations). If the producer
and the destination are in different buses then you can configure
the link or links between those buses to have no exception destination
(see Foreign buses and Configuring exception destination processing for a link to a foreign bus.
- Transaction roll-back
- The activation specification for a message-driven bean (MDB) can
specify a delay between failing message retries. This delay allows
time for the condition which causes the roll-back to recover before
the same message drives the MDB again. However, while a message is
delayed in this way, another (later) message can drive the MDB (see Protecting an MDB application from system resource problems). If this
is a problem for your application then consider limiting the maximum
sequential failures to one (see JMS activation specification [Settings] or
consider using strict message ordering, see Strict message ordering for bus destinations.
- Resolving indoubt transactions
- During two-phase commit processing, an application can fail while
a JMS send or receive operation is in an indoubt state. When this
happens, it is possible for the application to restart before the
indoubt state is resolved so that one or more messages are "invisible"
when the application restarts but become "visible" later. Other messages
on the destination are not affected. A consuming application can receive
a message (say message 2) which is logically after an "invisible"
message (say message 1); later, after the indoubt transaction is resolved,
the application receives the previously "invisible" message (message
1). In this way, the application might receive and process messages
in the wrong order. If this is a problem for your application then
consider using strict message ordering, see Strict message ordering for bus destinations.