Troubleshooting JMSCC0108 messages

There are a number of steps that you can take to prevent a JMSCC0108 message from occurring when you are using activation specifications and WebSphere® Application Server listener ports that are running in Application Server Facilities (ASF) mode.

When you are using activation specifications and WebSphere Application Server listener ports that are running in ASF mode, which is the default mode of operation, it is possible that the following message might appear in the application server log file:
JMSCC0108: The IBM MQ classes for JMS had detected a message, ready for asynchronous delivery to an application.
When delivery was attempted, the message was no longer available. 
Use the information in this topic to understand why this message appears, and the possible steps that you can take to prevent it from occurring.

How activation specifications and listener ports detect and process messages

An activation specification or WebSphere Application Server listener port performs the following steps when it starts up:
  1. Create a connection to the queue manager that they have been set to use.
  2. Open the JMS destination on that queue manager that they have been configured to monitor.
  3. Browse that destination for messages.
When a message is detected, the activation specification or listener port performs the following steps:
  1. Constructs an internal message reference that represents the message.
  2. Gets a server session from its internal server session pool.
  3. Loads the server session up with the message reference.
  4. Schedules a piece of work with the application server Work Manager to run the server session and process the message.

The activation specification or listener port then goes back to monitoring the destination again, looking for another message to process.

The application server Work Manager runs the piece of work that the activation specification or listener port submitted on a new server session thread. When started, the thread completes the following actions:
  • Starts either a local or global (XA) transaction, depending on whether the message-driven bean requires XA transactions or not, as specified in the message-driven bean's deployment descriptor.
  • Gets the message from the destination by issuing a destructive MQGET API call.
  • Runs the message-driven bean's onMessage() method.
  • Completes the local or global transaction, once the onMessage() method has finished.
  • Return the server session back to the server session pool.

Why the JMSCC0108 message occurs, and how to prevent it

The main activation specification or listener port thread browses messages on a destination. It then asks the Work Manager to start a new thread to destructively get the message and process it. This means that it is possible for a message to be found on a destination by the main activation specification or listener port thread, and no longer be available by the time the server session thread attempts to get it. If this happens, then the server session thread writes the following message to the application server's log file:
JMSCC0108: The IBM MQ classes for JMS had detected a message, ready for asynchronous delivery to an application.
When delivery was attempted, the message was no longer available. 
There are two reasons why the message is no longer on the destination when the server session thread tries to get it:

Reason 1: The message has been consumed by another application

If two or more activation specifications and/or listener ports are monitoring the same destination, then it is possible that they could detect the same message and try to process it. When this happens:
  • A server session thread started by one activation specification or listener port gets the message and delivers it to a message-driven bean for processing.
  • The sever session thread started by the other activation specification or listener port tries to get the message, and finds that it is no longer on the destination.
If an activation specification or listener port is connecting to a queue manager in any of the following ways, the messages that the main activation specification or listener port thread detects are marked: Marking a message prevents any other activation specification or listener port from seeing that message, and trying to process it.
By default, messages are marked for five seconds. After the message has been detected and marked, the five second timer starts. During these five seconds, the following steps must be carried out:
  • The activation specification or listener port must get a server session from the server session pool.
  • The server session must be loaded with details of the message to process.
  • The work must be scheduled.
  • The Work Manager must process the work request and start the server session thread.
  • The server session thread needs to start either a local or global transaction.
  • The server session thread needs to destructively get the message.

On a busy system, it might take longer than five seconds for these steps to be carried out. If this happens, then the mark on the message is released. This means that other activation specifications or listener ports can now see the message, and can potentially try to process it, which can result in the JMSCC0108 message being written to the application server's log file.

In this situation, you should consider the following options:
  • Increase the value of the queue manager property Message mark browse interval (MARKINT), to give the activation specification or listener port that originally detected the message more time to get it. Ideally, the property should be set to a value greater than the time taken for your message-driven beans to process messages. This means that, if the main activation specification or listener port thread blocks waiting for a server session because all of the server sessions are busy processing messages, then the message should still be marked when a server session becomes available. Note that the MARKINT property is set on a queue manager, and so is applicable to all applications that browse messages on that queue manager.
  • Increase the size of the server session pool used by the activation specification or listener port. This would mean that there are more server sessions available to process messages, which should ensure that messages can be processed within the specified mark interval. One thing to note with this approach is that the activation specification or listener port will now be able to process more messages concurrently, which could impact the overall performance of the application server.

If an activation specification or listener port is connecting to a queue manager running on a platform other than z/OS, using IBM MQ messaging provider migration mode, the marking functionality is not available. This means that it is not possible to prevent two or more activation specifications and/or listener ports from detecting the same message and trying to process it. In this situation, the JMSCC0108 message is expected.

Reason 2: The message has expired

The other reason that a JMSCC0108 message is generated is if the message has expired in between being detected by the activation specification or listener port and being consumed by the server session. If this happens, when the server session thread tries to get the message, it finds that it is no longer there and so reports the JMSCC0108 message.

Increasing the size of the server session pool used by the activation specification or listener port can help here. Increasing the server session pool size means that there are more server sessions available to process messages, which can potentially mean that the message is processed before it expires. It is important to note that the activation specification or listener port is now able to process more messages concurrently, which could impact the overall performance of the application server.