Message ordering
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 or SCA throttling for the default messaging provider). Alternatively, consider using strict message ordering, see Strict message ordering for bus destinations.
- 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. 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 or SCA application from system resource problems). If this is a problem for your application then consider limiting the maximum sequential failures to one on the JMS activation specification settings or consider using strict message ordering.
- 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.