5.6. JMS Integration or Provider

JMS integration in all Java EE servers is provided through JCA since it's a requirement of the specifications. As mentioned in Message Driven Beans section, there are two JMS providers: the original JBoss Messaging and the newer HornetQ technology. In either case, the focus in tuning each is the JCA thread pool.
The JCA container has its own thread pool, and this pool needs to be sized appropriately to handle the messaging load. It's highly related to the maxSession parameter that was discussed with message driven beans. Besides message driven beans, you can use the JMS API directly within the container, and not be tied to message driven beans at all. The JCA thread pool's configuration is in the file jca-jboss-beans.xml in the directory JBOSS_EAP_DIST/jboss-as/server/PROFILE/deploy. Note that the minimal configuration does not contain the JCA container.


Below is an example of this configuration file.
<!-- THREAD POOL -->
  <bean name="WorkManagerThreadPool" class="org.jboss.util.threadpool.BasicThreadPool">
<!-- Expose via JMX -->
<annotation>@org.jboss.aop.microcontainer.aspects.jmx.JMX(name="jboss.jca:service=WorkManagerThreadPool", exposedInterface=org.jboss.util.threadpool.BasicThreadPoolMBean.class)</annotation>
<!-- The name that appears in thread names -->
<property name="name">WorkManager</property>
<!-- The maximum amount of work in the queue -->
<property name="maximumQueueSize">1024</property>
<!-- The maximum number of active threads -->
<property name="maximumPoolSize">100</property>
<!-- How long to keep threads alive after their last work (default one minute) -->
<property name="keepAliveTime">60000</property>
In tuning the thread pool the focus is on just two parameters: maximumPoolSize and maximumQueueSize.
The maximumPoolSize parameter specifies the number of threads in the thread pool for use by the JMS provider. The default size is 100, which may or may not be appropriate. If message driven beans are used in the application, make sure that there are enough threads in the thread pool to handle the maximum number of sessions. If only one message driven bean is used, ensure that the thread pool is at least the size of the number of sessions for that one bean. If there are many different message driven beans, the calculations are more complex.
When you have many message-driven beans, each with their own maxSessions, start by adding all of the maxSession values together. This assumes that they all will hit those maximums at the same time, and different components are likely to have different usage patterns. If you understand the usage pattern, you may be able to reduce the thread pool accordingly, to just take into account the maximums that overlap each other. In fact, reducing it if you do not need 100 is a good step because it will save some memory.
If you are not sure of the application's behavior, you can monitor the usage of the thread pool through the JMX console. Below is a screen shot from the JMX console that shows the attributes of the thread pool:
JMX Console Thread Pool Statistics

Figure 5.4. JMX Console Thread Pool Statistics

On the second line of the table in the screenshot you see the attribute name called QueueSize, a read-only attribute which records any requests for threads from the thread pool that could not be satisfied because all the threads were currently in use. If this value is above zero, then the thread pool is too small to service all incoming requests. This value will not update automatically so it's necessary to refresh the page manually to see the value updated while the system is running.
The maximumQueueSize parameter specifies how many requests will wait for a thread to become available before an exception is thrown and processing is aborted. The default value is 1024, which is a safe value. You may want to fail fast, versus wait for an extended period of time, or have more than 1024 requests backed up before failing. Setting this parameter to a lower value means you'll know earlier of exceptions but at the expense of application uptime. It's recommended to leave it at the default value as it provides greater reliability. If a request is waiting in the queue it's because there are none available in the pool. While sizing the pool, monitor the number of requests waiting in the queue to confirm whether or not the pool is too small.