IBM WebSphere Application Server provides support for asynchronous messaging based on the Java™ Messaging Service (JMS) specification. Using either the WebSphere JMS provider or an external message provider, such as IBM WebSphere MQ, application developers can write message-driven beans (MDBs) that listen on a JMS destination (either a message queue or a topic) and then get invoked when a message arrives at that particular destination.
Listener ports are used by the application server to monitor JMS destinations, waiting for messages to arrive. When a message is detected, it is removed from the destination via the listener port, and forwarded on to the MDB for processing. Listener ports can be configured to deliver more than one message to an MDB at any one time, which enables batch processing of messages. It is also possible to configure a listener port to enable more than one message to be processed concurrently by an MDB.
This article discusses the effect that changing the maximum messages and maximum sessions properties has when using either the WebSphere Application Server V5 JMS Provider or IBM WebSphere MQ 5.3, with WebSphere Application Server Versions 5 and 6.
This article assumes a basic knowledge of JMS.
In general terms, a listener port's maximum messages property defines how many concurrent messages will be delivered to an MDB. These messages will be processed by the MDB in a single transaction, which gives the MDB the ability to perform "batch processing".
By default, this property has the value 1, which means that messages will be delivered to an MDB one at a time, and that each message will be processed within its own transaction. Increasing the value means that multiple messages will be delivered to an MDB in one go, and all of these messages will be processed within the same transaction. However, the downside to this is that, if either:
- the MDB has not finished processing all of the messages in the batch by the time the transaction timeout limit has been reached, or
- an error occurs while processing one of the messages in the batch
then all of the messages that the MDB has processed in that transaction up to this point will be rolled back.
A common misconception is that if you increase the value of the maximum messages property, an MDB must process exactly that number of messages before a transaction is committed. This is not the case. If the number of messages on a JMS destination is less than the value of the maximum messages property, all of the messages currently on the destination will be delivered to the MDB and processed within a single transaction. The MDB will not wait for new messages to arrive so that it can process a message batch that has a size equal to the maximum messages property -- if this were the case it is possible that messages would not be processed for a very long time!
Figure 1 shows the Listener Port Settings panel for the SamplePtoPListenerPort, used by a sample MDB application. This port has the maximum messages property set to 1.
Figure 1. Listener Port Settings
To understand how this property works, let's look at some examples.
Example 1
Suppose we have an MDB that is monitoring JMS destination destA. This destination has three messages on it : messageA, messageB and messageC. If the maximum messages property is set to the default value of 1, then the MDB will process the messages in the following sequence:
Example 1. Order in which messages are committed: messageA, messageB, messageC
| Seq. | Process task |
| 1 | Start a transaction. |
| 2 | Process messageA. |
| 3 | Commit the transaction. |
| 4 | Start a transaction. |
| 5 | Process messageB. |
| 6 | Commit the transaction. |
| 7 | Start a transaction. |
| 8 | Process messageC. |
| 9 | Commit the transaction. |
Example 2
If a problem occurs while processing messageB, the transaction will be rolled back and messageB will be returned to the JMS destination. The MDB will then process messageC, before trying to process messageB again. In this scenario, the sequence of events is as follows:
Example 2. Order in which messages are committed: messageA, messageC, messageB
| Seq. | Process task |
| 1 | Start a transaction. |
| 2 | Process messageA. |
| 3 | Commit the transaction. |
| 4 | Start a transaction. |
| 5 | Process messageB -- ERROR OCCURS. |
| 6 | Transaction rolled back. |
| 7 | Start a transaction. |
| 8 | Process messageC. |
| 9 | Commit the transaction. |
| 10 | Start a transaction. |
| 11 | Process messageB. |
| 12 | Commit the transaction. |
Example 3
Now, let's consider the situation where two new messages, messageD and messageE, arrive on the JMS destination while the MDB is processing messageB. If an error occurs while processing messageB and messageB is rolled back, the message will not be processed until messageC, messageD, and messageE have been processed:
Example 3. Order in which messages are committed: messageA, messageC, messageD, messageE, messageB
| Seq. | Process task |
| 1 | Start a transaction. |
| 2 | Process messageA. |
| 3 | Commit the transaction. |
| 4 | Start a transaction. |
| 5 | Process messageB -- ERROR OCCURS. |
| 6 | Transaction rolled back. |
| 7 | Start a transaction. |
| 8 | Process messageC. |
| 9 | Commit the transaction. |
| 10 | Start a transaction. |
| 11 | Process messageD. |
| 12 | Commit the transaction. |
| 13 | Start a transaction. |
| 14 | Process messageE. |
| 15 | Commit the transaction. |
| 16 | Start a transaction. |
| 17 | Process messageB. |
| 18 | Commit the transaction. |
What happens in these scenarios if we were to increase the value of the maximum messages property to 2?
In Example 1, above, the MDB would process the messages in two batches. The first batch would contain messageA and messageB. When the MDB has finished processing these two messages, it will process messageC:
Example 1a. Order in which messages are committed: messageA, messageB, messageC
| Seq. | Process task |
| 1 | Start a transaction. |
| 2 | Process messageA. |
| 3 | Process messageB. |
| 4 | Commit the transaction. |
| 5 | Start a transaction. |
| 6 | Process messageC. |
| 7 | Commit the transaction. |
Now, let's consider Example 2. The MDB will initially start a transaction, and process messageA. However, when processing messageB, an error occurs which causes both messageA and messageB to be rolled back.
The MDB will then start a new transaction, and process messageC, followed by messageA. After these messages have been processed, a third transaction will be started, which is used by the MDB to process messageB.
Example 2a. Order in which messages are committed: messageA, messageC, messageB
| Seq. | Process task |
| 1 | Start a transaction. |
| 2 | Process messageA. |
| 3 | Process messageB -- ERROR OCCURS. |
| 4 | Transaction rolled back. |
| 5 | Start a transaction. |
| 6 | Process messageC. |
| 7 | Process messageA. |
| 8 | Commit the transaction. |
| 9 | Start a transaction. |
| 10 | Process messageB. |
| 11 | Commit the transaction. |
For Example 3, the messages will be processed in a manner similar to Example 2a:
Example 3a. Order in which messages are committed: messageC, messageD, messageE, messageA, messageB
| Seq. | Process task |
| 1 | Start a transaction. |
| 2 | Process messageA. |
| 3 | Process messageB -- ERROR OCCURS. |
| 4 | Transaction rolled back. |
| 5 | Start a transaction. |
| 6 | Process messageC. |
| 7 | Process messageD. |
| 8 | Commit the transaction. |
| 9 | Process messageE. |
| 10 | Process messageA. |
| 11 | Commit the transaction. |
| 12 | Start a transaction. |
| 13 | Process messageB. |
| 14 | Commit the transaction. |
The maximum sessions property determines how many messages an MDB can process simultaneously. The default value for this property is 1, which means that an MDB must finish processing the first message on the queue before it can process the second, and so on (for you programmers, this essentially means that an MDB is single-threaded).
If the application server is not under a heavy load, you might want to increase the throughput of messages. In this situation, you can increase the value of the maximum sessions property to enable an MDB to process more than one message at once (this makes the MDB multi-threaded). It is worth noting, though, that increasing the value of maximum sessions will increase the load on your system, since you will now have multiple instances of the MDB running at the same time!
Figure 2 shows the Listener Port Settings panel for the SamplePtoPListenerPort, used by a sample MDB application. This port has the maximum sessions property set to 1.
Figure 2. Listener Port Settings
Once again, let's look at a couple of examples of how the maximum sessions property works.
Suppose we have an MDB that is monitoring JMS destination destA. This destination has three messages on it: messageA, messageB and messageC. If the maximum sessions property is set to its default value of 1, then the MDB will process the messages in the following sequence:
Example 4. Order in which messages are committed: messageA, messageB, messageC
| Seq. | Process task |
| 1 | Start a transaction. |
| 2 | Process messageA. |
| 3 | Commit the transaction. |
| 4 | Start a transaction. |
| 5 | Process messageB. |
| 6 | Commit the transaction. |
| 7 | Start a transaction. |
| 8 | Process messageC. |
| 9 | Commit the transaction. |
What happens if we increase the value of maximum sessions to 2?
Now, the MDB can process two messages at the same time. When the application server starts up, it creates two separate instances of the MDB, which we shall call mdbInstance1 and mdbInstance2. mdbInstance1 would process messageA, while mdbInstance2 will process messageB.
But who processes messageC? The answer to that question is: whichever MDB instance finishes processing its message first.
For example, if mdbInstance1 finished processing messageA before mdbInstanceB finished processing messageB, then mdbInstance1 would take messageC off of destA and start processing it. When mdbInstance2 has finished with messageB, it will wait for a new message to arrive on the destination.
Example 5. Order in which messages are committed: messageA, messageB, messageC
| Seq. | mdbInstance1 | mdbInstance2 |
| 1 | Start a transaction | |
| 2 | Start a transaction | |
| 3 | Process messageA | |
| 4 | Process messageB | |
| 5 | Commit the transaction | |
| 6 | Commit the transaction | |
| 7 | Start a transaction | |
| 8 | Process messageC | |
| 9 | Commit the transaction |
However, if mdbInstance2 finishes processing messageB before mdbInstance1 has finished with messageA, then messageC would be delivered to mdbInstance2.
Example 6. Order in which messages are committed: messageB, messageA, messageC
| Seq. | mdbInstance1 | mdbInstance2 |
| 1 | Start a transaction | |
| 2 | Start a transaction | |
| 3 | Process messageA | |
| 4 | Process messageB | |
| 5 | Commit the transaction | |
| 6 | Commit the transaction | |
| 7 | Start a transaction | |
| 8 | Process messageC | |
| 9 | Commit the transaction |
Process messages in a strict order
The only way to ensure that messages are processed in the order in which they appear on a JMS destination (without coding logic into the MDB itself) is to set the value of both properties to 1. This means that you have a single instance of an MDB that processes messages in batches of 1 message per transaction.
Suppose you have a client application, Client1, that puts messageA, messageB, and messageC onto a JMS destination. With the maximum sessions and maximum messages properties both set to 1, the messages will be committed in the following sequence: messageA, messageB, messageC -- assuming, of course, that the each message was processed successfully and was not rolled back.
Now, suppose we increase the value of maximum sessions to 2. This means that our MDB can process two messages concurrently. If our JMS destination contains the messages messageA, messageB, and messageC (in that order), then when the MDB starts up, it will start processing messageA and messageB at the same time; when one of the MDB instances has finished processing its message, it will process messageC. The scenario we want is this:
Example 7. Order in which messages are committed: messageA, messageB, messageC
| Seq. | mdbInstance1 | mdbInstance2 |
| 1 | Start a transaction | |
| 2 | Start a transaction | |
| 3 | Process messageA | |
| 4 | Process messageB | |
| 5 | Commit the transaction | |
| 6 | Commit the transaction | |
| 7 | Start a transaction | |
| 8 | Process messageC | |
| 9 | Commit the transaction |
However, as we have seen, there is no guarantee that the MDB will finish processing messageA before it finishes processing messageB. This means that we are equally likely to have this scenario:
Example 8. Order in which messages are committed: messageB, messageA, messageC
| Seq. | mdbInstance1 | mdbInstance2 |
| 1 | Start a transaction | |
| 2 | Start a transaction | |
| 3 | Process messageA | |
| 4 | Process messageB | |
| 5 | Commit the transaction | |
| 6 | Commit the transaction | |
| 7 | Start a transaction | |
| 8 | Process messageC | |
| 9 | Commit the transaction |
Suppose we increase the value of maximum messages to 2, and leave Maximum sessions at 2.
If our JMS destination contains messageA, messageB, messageC, and messageD, then when the MDB starts up, it will start processing two batches of messages. As we have already seen in the previous paragraph, setting the maximum sessions property to a value greater than 1 means that we cannot predict which messages will be processed first.
In this situation, there is no guarantee that the first batch of messages will be processed before the second batch. There is also no guarantee that the first batch of messages will contain messageA and messageB, nor that the second batch will consist of messageC and messageD. We could have this:
Example 9a. Order in which messages are committed: messageA, messageB, messageC, messageD
| Seq. | mdbInstance1 | mdbInstance2 |
| 1 | Start a transaction | |
| 2 | Start a transaction | |
| 3 | Process messageA | |
| 4 | Process messageC | |
| 5 | Process messageD | |
| 6 | Process messageB | |
| 7 | Commit the transaction | |
| 8 | Commit the transaction |
but we could just as easily get this:
Example 9b. Order in which messages are committed: messageC, messageD, messageA, messageB
| Seq. | mdbInstance1 | mdbInstance2 |
| 1 | Start a transaction | |
| 2 | Start a transaction | |
| 3 | Process messageC | |
| 4 | Process messageD | |
| 5 | Process messageA | |
| 6 | Process messageB | |
| 7 | Commit the transaction | |
| 8 | Commit the transaction |
or this:
Example 9c. Order in which messages are committed: messageA, messageC, messageB, messageD
| Seq. | mdbInstance1 | mdbInstance2 |
| 1 | Start a transaction | |
| 2 | Start a transaction | |
| 3 | Process messageA | |
| 4 | Process messageB | |
| 5 | Process messageC | |
| 6 | Process messageD | |
| 7 | Commit the transaction | |
| 8 | Commit the transaction |
or even this:
Example 9d. Order in which messages are committed: messageB, messageD, messageA, messageC
| Seq. | mdbInstance1 | mdbInstance2 |
| 1 | Start a transaction | |
| 2 | Start a transaction | |
| 3 | Process messageB | |
| 4 | Process messageA | |
| 5 | Process messageC | |
| 6 | Process messageD | |
| 7 | Commit the transaction | |
| 8 | Commit the transaction |
We have seen how the listener port's maximum messages and maximum sessions properties affect the order in which MDBs process messages, how these two properties work together, and what effect poison messages have on message delivery. Use this information to configure the most appropriate property values to achieve the results you need from your application.
- Simplify applications by using WebSphere Extended Messaging
- WebSphere V5 Extended Messaging support
- Creating extended messaging applications for WebSphere Application Server V5
- Interfacing WebSphere Extended Messaging with existing message applications
- How WebSphere Application Server handles poison messages
- Get involved in the developerWorks community, participate in developerWorks blogs.
- Browse for books on these and other technical topics.
Paul Titheridge joined IBM in September 1995, after graduating from Exeter University. Following spells in the Voice and Business Integration departments, Paul is currently a member of the WebSphere and Java Messaging Support team, resolving problems for customers who use WebSphere MQ and WebSphere Application Server.




