Optimizing JMS Performance
This section looks at how to optimize the performance of the JMS server. We examine how message quotas for the JMS server and/or the destinations can be used to limit the number of messages that can be stored in memory. We look at how to enable paging, and how to enable the JMS server to throttle the rate of message production under load. Both message paging and flow control rely on a set of threshold values that determine when the JMS server and/or destinations are considered to be under load.
After this, we devote our attention to improving the performance of JMS file stores and to achieving the ideal setup for the JDBC connection pool associated with a JDBC store. We also cover the active message expiration feature provided by WebLogic 8.1, and the various ways in which the JMS server can handle expired messages. Finally, we discuss the two important ways of implementing concurrent messaging, and in particular, probe the use of server session pools.
8.2.1 Message Quotas
Quotas allow you to restrict the number of messages that can be held in memory. These limits can be specified in terms of either the maximum number of messages or the maximum cumulative size of the messages (in bytes). WebLogic JMS lets you configure message quotas for both the JMS server and the destinations it hosts. The relevant settings, available within the Thresholds & Quotas tab for the chosen JMS server or destination, are as follows:
Messages Maximum
Use this setting to determine the maximum number of messages that can be retained in memory.
Bytes Maximum
Use this setting to set the upper limit on the cumulative size of all messages held in memory.
Do not confuse the Messages Maximum setting here with the Messages Maximum setting for a connection factory. The latter indicates the maximum number of messages that may be placed in an asynchronous session's pipeline.
|
Message quotas that are set for a destination determine the maximum number of bytes or messages that can be stored in the destination, while message quotas for a JMS server determine the maximum number of bytes or messages that can be stored in the JMS server. If a producer tries to send messages that exceed the quotas set for the JMS server or destination, a javax.jms.ResourceAllocationException exception is thrown, and the message will not be delivered. One possible action to take in these circumstances is to pause before resending the message.
8.2.2 Message Paging
Unless messaging paging has been enabled, all messages that arrive at the JMS server, regardless of whether they are persistent, are held in memory. This is an important aspect of the JMS server that you need to keep in mind when architecting a solution. Fortunately, WebLogic provides a message paging facility that allows the JMS server to move messages from memory to persistent storage during specified load conditions. The message header and property fields will continue to remain in memory, even though the body of the messages may be swapped out to the paging store. This ensures that more virtual memory is made available to the JMS server when it is under load. Message paging does not affect your JMS applications in any way. It occurs transparently on the JMS server. The only side effect of message paging is that it may slow down the server. Clearly, paging to a persistent store will be more expensive than not paging at all, so you should balance the paging thresholds to ensure that paging occurs only when you need it.
In order to support paging for nonpersistent messages, you must configure a paging store for the JMS server. Persistent messages, however, do not require a paging store. They will automatically use persistent JMS stores configured for the server or destination. Because paging is quite performance-intensive, we recommend that you use file stores for message paging, and not for JDBC stores. Moreover, if a JMS store serves as a paging store for a JMS server, it cannot be used for other purposes, such as for capturing persistent messages or durable subscriptions. Nor can paging stores be shared by multiple JMS servers. If your domain includes multiple JMS servers, you must create a separate paging store for each.
8.2.2.1 How paging works
WebLogic supports two forms of paging: bytes paging and message paging. Each form uses a different measurement for determining when paging occurs and for how long. Bytes paging uses the number of bytes consumed by the messages on the JMS server as its primary measurement, while message paging uses the number of messages that are stored on the JMS server. Let's examine how bytes paging works on the JMS server. The same discussion also holds true for message paging.
Paging occurs on the basis of two settings: a high and a low threshold. The high threshold is used to start the paging mechanism. If the cumulative size (in bytes) of all messages stored on the JMS server exceeds the high threshold, the JMS server starts swapping in-memory messages out to the store. This paging mechanism remains in place until the number of bytes consumed by the messages on the JMS server falls below the low threshold value. Thus, the high threshold value determines only when the paging starts, at which point the server is said to be armed. Once this point is reached, the JMS server ignores the high threshold, and the low threshold determines when the paging stops.
8.2.2.2 Configuring paging for servers and destinations
Message paging can be configured for a JMS server and/or individual destinations. For a JMS server, you can specify the paging store, enable bytes or message paging, and set the appropriate threshold values. Similarly, for a JMS destination, you can enable bytes and/or message paging, and set the appropriate threshold values. In this case, the destination uses the paging store configured for the JMS server. By default, message paging is not enabled for the JMS server or any of its destinations. However, if you enable either bytes or message paging on the JMS server or any of its destinations, WebLogic automatically will create a paging store for the JMS server, even if you didn't configure one manually.
You can set the paging store for a JMS server using the Administration Console. Simply navigate to the Configuration/General tab for the desired JMS server and then choose from one of the existing JMS file stores. Once you've configured the paging store, you must navigate to the Thresholds & Quotas tab and specify values for the following attributes:
Bytes Paging Enabled
Check this option to enable bytes paging on the JMS server.
Bytes Threshold High
Use this option to determine when bytes paging starts i.e., when the cumulative size of the messages on the JMS server exceeds this threshold value.
Bytes Threshold Low
Use this option to determine when bytes paging stops i.e., when the cumulative size of the messages on the JMS server falls back below this threshold value.
Message Paging Enabled
Check this option to enable message paging on the JMS server.
Messages Threshold High
Use this option to determine when message paging starts i.e., when the number of messages on the JMS server falls back below this threshold value.
Messages Threshold Low
Use this option to determine when message paging stops i.e., when the number of messages on the JMS server falls back below this threshold value.
Note that it is not enough that you simply enable the Bytes/Message Paging Enabled options. You also must specify positive values for the appropriate thresholds. Similarly, if you just configure the thresholds but do not enable either bytes or message paging, the JMS server will just log the threshold conditions when they occur, and take no action. Once paging has been enabled, it cannot be dynamically disabled by setting the paging thresholds to -1. Instead, you can set the high threshold to a very large number, to prevent paging from being triggered.
|
You can set up message paging on an individual destination as well. The same paging thresholds can be configured for a destination from the Thresholds & Quotas tab.
You can also use the Thresholds & Quotas tab to adjust the paging behavior for a JMS template, in which case all destinations that use the selected template will inherit the settings. For this reason, the Bytes/Message Paging Enabled options for a destination accept an additional value, default, which implies that its value is inherited from the template assigned to the destination. In other words, paging is enabled on the destination, provided that the Bytes/Message Paging Enabled options have been set on the template associated with the destination. On the other hand, you can explicitly set the Bytes/Message Paging Enabled options on a destination to true or false to override the values inherited from the template.
Note that if message paging is enabled on a JMS server but not on a destination hosted by the JMS server, messages arriving at the destination still can be swapped to the store when paging is initiated on the server. In this case, if message paging is disabled on a destination, paging will not be triggered if the messages stored on the destination exceed the high threshold set for the destination.
8.2.3 Flow Control
In general, producers send messages at a much faster rate than consumers can handle them, and in some situations, overactive producers can swamp consumers. This in turn can degrade the performance of the JMS servers and further aggravate the situation. WebLogic provides a flow control feature that allows the JMS server or destination to throttle the producers by suppressing the rate at which the messages are produced. Flow control works by delaying the time it takes for calls to produce a message to return. The flow control mechanism kicks in when the JMS server or destination exceeds its specified bytes or message upper threshold. In fact, the flow control mechanism uses the same "paging" thresholds defined for the JMS server or destination to decide if the server is still armed.
The flow control mechanism can be enabled on a connection factory. The flow control settings on the connection factory then permeate through to the JMS connections created by the factory, and then to the JMS sessions created from those connections, and finally to the JMS producers that use the connection factory. The Configuration/Flow Control tab for a selected connection factory holds the configuration settings. Tick the Flow Control Enabled option to enable flow control for all message producers created using the factory. The other settings provide a way of tuning the flow control.
8.2.3.1 How flow control works
A connection factory defines settings that limit the rate of flow of messages of its producers within a minimum and maximum range. As conditions degrade, the producers will send messages at a rate that tends toward the flow minimum range; as conditions improve, the producers will send messages at a rate that will gradually tend toward the flow maximum range. Once flow control has come into effect, the producers check at configured intervals if the threshold conditions still apply and if the need for flow control still exists. This, along with the number of flow steps, defines the rate at which the production rate moves toward the flow minimum or flow maximum ranges.
The flow control mechanism ensures that the production rate degrades at a faster rate than it improves. The decay in message production follows a geometric progression, whereas the increase follows a linear algorithm. The following sequential steps outline the flow control mechanism in operation:
- When a JMS server or destination exceeds its bytes or message upper threshold, it becomes armed and the flow control mechanism kicks in for all producers of a connection factory for which flow control has been enabled.
- Once the server or destination is armed, the flow control settings on the connection factory kick in and work toward limiting the message flow of its producers. Under these conditions, the producers instantly will be limited to sending messages at a rate that never exceeds the configured flow maximum number of messages per second. In fact, when a producer is flow-controlled, the rate of message production will be bound by the flow minimum and flow maximum ranges.
- Starting from the specified flow maximum value, a producer will then periodically determine whether the server or destination is still armed. In fact, it is the flow interval that determines the time period (in seconds) after which the producers check for threshold conditions. If, after the interval, the server or destination is still armed, the producer further throttles its production rate. This can continue until the rate of message production reaches the flow minimum number of messages per second.
- As all of the producers slow down, the threshold condition in the server or destination gradually corrects itself until it becomes unarmed. A producer is then allowed to increase its production rate again, in a controlled way, until the rate eventually reaches the flow maximum range. Only after the message production reaches the flow maximum is the producer released from all flow control.
As you can see, once a server or destination is armed, flow control ensures that the rate of message production fluctuates between the flow minimum and flow maximum ranges. Once the server or destination is unarmed, the rate of message production is allowed to increase in a controlled way up to the flow maximum, after which the flow control mechanism is disengaged. Finally, in order to determine whether the server or destination is still armed, and thus whether the producers must still be controlled, WebLogic uses the bytes or message thresholds configured for the JMS server or destination.
8.2.3.2 Tuning the flow control mechanism
Now, let's revisit the configuration settings that impact the flow control mechanism on all producers of a JMS connection factory. From the Configuration/Flow Control tab for a selected connection factory, you can adjust the following attributes:
Flow Maximum
This setting determines the maximum number of messages per second for producers when the server or destination is experiencing a threshold condition. During these conditions, the rate of message production will never exceed this limit.
Flow Minimum
This setting determines the minimum number of messages per second for producers when the server or destination is experiencing a threshold condition. During these conditions, the rate of message production will never go below this limit.
Flow Interval
This setting defines the adjustment time period (in seconds) for all producers experiencing flow control. Once the flow control is in effect, the producers check at regular intervals to see whether the server is still armed and determine whether producers still need to be throttled.
Flow Steps
This setting defines the number of steps needed to move the production rate from the Flow Maximum down to the Flow Minimum (or vice versa). At each flow step, the producers adjust their flow, either upward or downward, depending on the current conditions.
In addition, you must set the appropriate flow control thresholds from the Thresholds & Quotas tab for the JMS server or destination:
Bytes/Messages Threshold High
Flow control kicks in when the number/size of the messages stored on the JMS server or destination exceeds this threshold value.
Bytes/Messages Threshold Low
The server or destination becomes unarmed when the number/size of the messages on the JMS server or destination falls below this threshold value. Flow control still remains in effect until the producers move their rate upward and go beyond the flow maximum.
8.2.3.3 Blocking message producers
WebLogic 8.1 supports additional flow control features for temporarily blocking message producers from sending messages when the JMS destination has exceeded its message quota limit:
Blocking Send Policy
This setting determines the blocking strategy that is adopted by the JMS server when multiple producers are competing for space on a JMS destination that has reached its maximum quota limit. For instance, you can choose a blocking strategy so that the JMS server allows smaller messages to be delivered to the destination when larger ones are still waiting for space.
Send Timeout
By setting a send timeout value on a connection factory, this setting lets you allow the producers to wait for a specific length of time until space becomes available on a JMS destination that has reached its maximum quota limit.
To determine how the JMS server blocks send requests when a destination has reached its maximum quota, you must navigate to the Configuration/Thresholds & Quotas tab for the desired JMS server. Here you can specify two values for the Blocking Send Policy setting:
FIFO
The FIFO policy ensures that all send requests for the destination are queued up until further space becomes available. A send request cannot complete until the send requests before it have been completed. This is the default policy.
Preemptive
The preemptive policy enables the JMS server to allow smaller send requests to proceed to the destination if there is space for them, preempting other send requests that also are blocked on the destination. The JMS server permits those send requests that can be accommodated by the destination as and when space becomes available, while remaining within the message quota limits.
The Send Timeout feature is an additional flow control mechanism that ensures that any send requests to a destination do not cause the destination to exceed its message quota limits. It provides message producers with the option of pausing for a specific length of time until enough space becomes available on the destination. Instead of just slowing down message production, you can block the producers completely for a specific period of time. The producer will then block until more space on the destination becomes available, or until the operation times out. In order to configure the send timeout, select a JMS connection factory from the left pane and then navigate to the Configuration/Flow Control tab. For the Send Timeout attribute, specify the maximum number of milliseconds that a sender should wait on a JMS destination that has reached its maximum quota. By default, JMS producers are blocked for 10 milliseconds when a destination has reached its maximum quota.
You can disable the Send Timeout feature altogether by setting this attribute to 0. In that case, a sender will instantly receive a "resource allocation" exception if the message quota on the JMS destination has been reached. If you specify a positive value for the Send Timeout attribute, a sender will receive this exception only after it has waited for the specified timeout period. If the producers are running on the server itself, it is best to keep the Send Timeout to a low value, so as to avoid blocking the sender for too long.
8.2.4 JMS Stores
Earlier we looked at how to configure both a file store and a JDBC store for a JMS server, and noted that the file store is considerably faster. In this section, we examine how you can improve the performance of JMS file stores. We also deal with how to manage the database tables for a JDBC store and the ideal settings for the JDBC connection pool that provides access to the backend database. Using a store invariably will slow down the application. For this reason, try to ensure that the persistent quality of service is used only when it is needed and should be used.
8.2.4.1 Tuning file stores
File I/O manifests in two forms. Asynchronous I/O usually involves accumulating the data that must be written in the OS buffers, and then writing the data periodically to the file. Synchronous I/O, on the other hand, typically involves blocking the application until the I/O operation completes, thereby ensuring that the data is written to disk. For this reason, synchronous I/O is typically far slower but more reliable than asynchronous I/O. Synchronous writes to a file store ensure that the data is written to the disk it's what guarantees up-to-the-message integrity. Asynchronous writes to a file store possibly can result in lost information if the I/O buffer is lost during a machine crash. Note that the data in the I/O buffers will be lost only in the event of a severe crash. If you simply shut down an application server or the operating system itself, no data will be lost because the OS will flush all I/O buffers to disk. In fact, there are two I/O buffers to consider here: the I/O buffers of the OS itself, and an I/O buffer in the disk hardware. Appropriate disk hardware can reduce the risk of loss of data in the on-disk I/O cache.
By default, WebLogic's JMS guarantees up-to-the-message integrity via synchronous writes to a file store. In other words, transactions cannot complete until all writes to the JMS file store have been flushed to disk. You can, however, change the write policy to trade integrity for performance. This loss of integrity means that you may possibly lose sent messages or receive the same messages more than once (even if the messages are transactional) in the event of a severe crash.
You have to bear all of these considerations in mind when configuring the Synchronous Write Policy mode for a JMS file store. In fact, you can choose from the following three options:
Cache-Flush
This ensures that transactions cannot complete until all writes have been flushed to disk. This is the default setting for a JMS store and the most reliable, though not the fastest.
Direct-Write
This ensures that data is written directly to disk implementing the synchronous I/O scheme. This policy is supported only on Sun Solaris, HP, and Windows systems (including 64-bit platforms). If you choose this policy for an unsupported OS, the cache-flush policy is used instead.
Disabled
This disables the synchronous policy altogether, and thus enables both the OS cache and filesystem's on-disk cache to be used. Because both I/O caches are in operation, the I/O is no longer synchronous, and so its performance is dramatically increased.
The scalability, performance, and reliability of these schemes will vary depending on your OS and disks. In general, disabling the synchronous write policy leads to the fastest and most scalable option for a file store, although it presents some risk of loss. The default cache-flush policy offers high reliability and reasonably good performance. The direct-write policy with good hardware provides high reliability but lesser performance.
The performance and scalability of the direct-write policy also depend on whether an on-disk cache is enabled. For instance, direct writes on Solaris systems are transactionally safe because they don't rely on an on-disk cache. On the other hand, Windows systems do rely on an on-disk cache. Moreover, the direct-write policy on Windows systems may not directly write, since data may be left in the on-disk cache. To guarantee absolute integrity, you must either disable the on-disk cache or use a disk with a reliable, backed cache.
Further performance improvement can be gained by placing file stores on separate disks. In particular, try to avoid sharing the disk used by a JMS store with the disk used for the transaction logs or another JMS store. Utilizing high-performance disks is even better. All of this may seem like an overemphasis on the performance of JMS stores, but a well-tuned JMS store plays an important role in achieving good performance for the JMS server.
8.2.4.2 Managing the JMS tables for a JDBC store
WebLogic automatically creates the tables needed to represent a database-backed JMS store. When you configure a JDBC store, the JMS server creates two tables for private use: JMSStore and JMSState. These table names optionally can include a prefix to uniquely identify the tables associated with the JMS store. This prefix can take the form:
[[catalog.]schema.]prefix
A prefix must uniquely identify the JMS-related tables, and is generally needed only if multiple JMS stores have to be able to coexist in the same database, or to differentiate between the JMS tables of two different WebLogic instances that use the same database. It is important that all such tables are unique to each store and server. A table shared between multiple JMS stores will result in data corruption.
If these JMS-related tables become corrupted for some reason, you can use the utils.schema utility to regenerate them. The utility simply deletes all existing tables associated with the JMS store and re-creates them. For this reason, you should use this tool with caution.
As usual, you must set up your environment to include the weblogic.jar library. You can accomplish this by executing the setEnv batch file provided by WebLogic. In order to invoke the tool, you must supply the name of the DDL file that holds the SQL commands needed to re-create the JMS tables on the target database. The weblogic/jms/ddl directory within the weblogic.jar contains the DDL files for all the supported databases. Unpack the relevant DDL file from the JAR, and modify it suitably (for instance, if you must attach a prefix before all table names).
Then, you can run the tool by passing in the database URL, the driver class name, and the name of the DDL file:
java utils.Schema url JDBC_driver [-u username] [-p password] file.ddl
Running this command merely sends the SQL DDL commands to the database. Thus, in order to re-create the JMS tables on an MS SQL Server database, you can use the default DDL file supplied in the weblogic.jar library as follows:
java utils.Schema jdbc:microsoft:sqlserver://localhost:1433 com.microsoft.jdbc.sqlserver.SQLServerDriver -u oracle -p rules weblogic/jms/ddl/jms_mssql.ddl
8.2.4.3 Configuring the JDBC pool for a JMS store
When configuring a JDBC store, you also must assign an existing JDBC connection pool to the JMS store. This connection pool has to be targeted to the WebLogic instance that hosts the JMS server because it enables the JMS server to access the backend database. If a JDBC connection pool is to be used by a JMS server to interact with a JDBC store, you also must follow certain guidelines when configuring the connection pool. First, you have to ensure that the JDBC connection pool uses a non-XA driver. In other words, the connection pool must not use an XA-aware JDBC driver, nor should you enable the "Emulate Two Phase Commit for non-XA Driver" option for the connection pool. Because WebLogic's JMS provider is its own resource manager in a distributed transaction, it handles all the support for distributed transactions without relying on any XA support from the JDBC connection pool.
So, as far as distributed transactions are concerned, an XA data source and a JMS server are considered two separate resources, even if the underlying connection pools may point to the same database. The cost of enforcing the two-phase commit protocol can be alleviated somewhat by collocating the connection pool being used for the JMS store, with the JMS destination itself and the other XA resources participating in the transaction. In this way, WebLogic can optimize distributed transactions when both resources reside on the same server because it is able to avoid the network overhead.
Recall how JDBC stores offer the advantage of being easily accessible to multiple servers. As a result, if a WebLogic instance hosting a JMS server fails, it becomes easier to migrate the JMS server and related resources to another WebLogic instance. However, do note that a JDBC store presents its own point of failure as well. If the backend database goes down, the connections within the connection pool certainly will be broken, unless you've set the "Test Connections on Reserve" attribute on the pool. In this way, the JDBC connection pool can automatically reconnect to a failed database once it's brought back alive, without having to restart WebLogic Server. This mechanism allows the associated JDBC store to easily recover from database failures.
8.2.5 Message Expiration
Message expiration has been greatly enhanced in WebLogic 8.1. In previous WebLogic releases, the message expiration mechanism was passive. When a message expired, nothing happened. Of course, the expired messages were never delivered, but they were not actively cleaned up either. Rather, messages expired as and when they were encountered during the course of normal operations of the JMS server, after which they simply would be discarded. However, in WebLogic 8.1, the JMS server can be configured to actively scan for expired messages. How the JMS server treats these expired messages also can be adjusted differently for individual destinations. For instance, a destination could be configured so that the JMS server logs any expired messages discovered during the scan, or perhaps it sends them to a designated error destination.
8.2.5.1 Enabling active message expiration
By regularly scanning for expired messages, the JMS server can ensure that the expired messages do not accumulate on the destinations and hog server resources. To configure the active message expiration mechanism, you must select a JMS server from the Administration Console and then navigate to the Configuration/General tab. The value of the Expiration Scan Interval setting defines how often WebLogic will scan for expired messages. The default value is 30 seconds. If you set this interval to 0, WebLogic will never scan the destinations for expired messages. In other words, the messages will expire passively, which is the typical mode of expiry in WebLogic 7.0 and earlier.
8.2.5.2 Expired message handling
Previous releases of WebLogic simply would discard any expired messages, as and when they were discovered. In WebLogic 8.1, you can instruct the JMS server to take specific actions when expired messages are discovered. Expired messages now can be discarded, logged, or sent to an error destination. This expiration policy can be defined on a per-destination basis. You also can define the expiration policy on a JMS template, which is then common to all destinations that use that template. In order to adjust the expiration policy, you must select the Expiration Policy tab for a chosen destination or template, and then choose from one of the following options for the Expiration Policy attribute:
None
If a template has been assigned to the destination, this option is used to inherit the expiration policy configured for its template. Otherwise, this option is equivalent to "Discard."
Discard
This option causes expired messages to be removed from the system without logging or redirection.
Log
This option removes any expired messages that are discovered, and writes an entry to the server log file indicating that the messages were removed.
Redirect
This option moves all expired messages to the error destination configured for the destination.
If you decide to log all expired messages, you also can set the Expiration Logging Property attribute. This setting determines what information pertaining to the expired JMS message is actually written to the server's logs, over and above the JMSMessageID field. You can use %header% to indicate that all header fields should be logged, %properties% to indicate that all user properties should be logged, and the names of any JMS header fields (both standard and WebLogic-specific) or any user-defined properties. Here are a few examples:
%header%, Name, JMSPriority %properties%, JMSCorrelationID
8.2.6 Concurrent Messaging
WebLogic JMS supports a pool of server-side sessions, a mechanism that allows an application to concurrently process messages arriving at various JMS destinations. MDBs provide another way to concurrently handle messages arriving on a destination. At deploy time, WebLogic creates a pool of EJB instances of the same MDB, dedicated to processing messages arriving at a preconfigured topic or queue. Conceptually, MDBs are quite similar to JMS session pools. Both provide a pool of resources that enable the application to process incoming messages concurrently. There are a few vital differences, though:
- MDBs can be attached to any JMS server, even to destinations on foreign JMS servers. However, session pools may be configured only for servers that use WebLogic's JMS provider.
- MDBs need not be deployed to the same WebLogic instance that hosts the JMS destination. On the other hand, session pools are configured on the JMS server itself, and hence always will reside on the same server that hosts the JMS destinations.
- MDBs can be transactional and can be used within the context of a two-phase commit transaction. JMS sessions within a session pool, however, do not support JTA transactions. They support only standard transacted sessions.
- You can attach multiple consumers to the same session pool. In this way, a single message listener can be used to handle messages arriving on multiple destinations. On the other hand, an MDB can be attached to a single JMS destination only.
MDBs are a standard requirement of any J2EE-compliant application server. Session pools are an optional feature of the JMS API, and thus may not be implemented by all vendors. For these reasons, we recommend that you always use MDBs instead of session pools. Chapter 10 explains how to build and deploy MDBs.
8.2.6.1 Using JMS session pools
You can associate a number of session pools with a JMS server, where each pool represents a collection of JMS sessions that can be invoked concurrently. Once again, you must use the Administration Console to configure a session pool, and then bind one or more connection consumers to the session pools. You can accomplish the same tasks programmatically using the public API provided by WebLogic JMS, which includes the classes and interfaces under the weblogic.jms.extensions package.
To create a new session pool using the Administration Console, expand a JMS server node from the left pane and then select the Session Pools node. Then choose the "Configure a new JMS Session Pool" option to proceed. Here, you must specify values for the following configuration settings:
Name
Use this option to specify a logical name for the server session pool.
Connection Factory
Use this setting to specify the JNDI name of the connection factory to be used for creating the JMS sessions in the pool.
Listener Class
Use this setting to determine the fully qualified name of the message listener class.
Transacted
Use this setting to indicate if the JMS sessions within the pool will be transacted.
Acknowledge Mode
Use this setting to determine the acknowledge mode employed by the nontransacted JMS sessions. If the sessions within the pool are transacted, this setting is ignored.
Sessions Maximum
Use this setting to set the maximum number of JMS sessions in the pool. A value of -1 indicates that there is no limit to the size of the session pool.
Once you hit the Create button, a new session pool appears under the Session Pools node in the left pane. Now we need to set up a number of consumers for the sessions. To accomplish this, you should expand the new server session node, select the Consumers child node from the left pane, and click the "Configure a new JMS Connection Consumer" option. The settings here are identical to the arguments that you would supply to the createConnectionConsumer( ) method, had you set up the consumer programmatically:
Messages Maximum
This attribute determines the maximum number of messages that may be loaded into a session at one time by the connection consumer.
Selector
This attribute lets you associate a message selector with the connection consumer.
Destination
This attribute specifies the JNDI name of the destination to be used.
You can attach multiple connection consumers to a server session pool. The session pool will be created when the JMS server starts up, and any consumers configured to the session pool immediately will be made ready for concurrent processing. Note that because the message listener class runs on the server, you must ensure that the class is available in the classpath of the particular WebLogic instance that hosts the JMS server with the server pool.
To create a session pool programmatically, you need to look up a WebLogic-specific ServerSessionPoolFactory object from the JNDI tree, which then can be used to generate a session pool. WebLogic automatically binds a session pool factory in the server's JNDI tree. The JNDI name for this factory can be determined by appending the name of the JMS server to the string weblogic.jms.ServerSessionPoolFactory:. So, you could look up the default server session pool factory from a WebLogic instance hosting a JMS server called MyJMSServer as follows:
ServerSessionPoolFactory factory = (ServerSessionPoolFactory) ctx.lookup("weblogic.jms.ServerSessionPoolFactory:MyJMSServer"); // use the factory to create a session pool
Now let's look at how to create a session pool on a JMS server called MyJMSServer, using the message listener class oreilly.wlguide.jms.PoolReceiver. First, you must retrieve a queue connection factory and obtain a reference to the queue:
QueueConnectionFactory qf = (QueueConnectionFactory) ctx.lookup("oreilly.myConnectionFactory"); QueueConnection qcon = qf.createQueueConnection( ); Queue queue = (Queue) ctx.lookup("MyQ"); qcon.start( );
All this is standard JMS code. The initial setup is similar to how you would create a queue receiver. But instead of explicitly creating a JMS session, you now will dip in to the newly created session pool. Here's how you can obtain the session pool factory from the JNDI namespace and then create a ServerSessionPool object:
ServerSessionPoolFactory sessionPoolFactory = (ServerSessionPoolFactory) ctx.lookup("weblogic.jms.ServerSessionPoolFactory:MyJMSServer"); ServerSessionPool sessionPool = sessionPoolFactory.getServerSessionPool(qcon, 8, false, Session.AUTO_ACKNOWLEDGE, "oreilly.wlguide.jms.PoolReceiver");
The getServerSessionPool( ) method lets you create a session pool. This method accepts the following arguments: a queue connection, the pool size, whether the sessions are transacted, the acknowledge mode for all transactions, and the message listener class. You then can attach a connection consumer to a server session pool by calling the createConnectionConsumer( ) method on the queue connection:
ConnectionConsumer cr = qcon.createConnectionConsumer( queue, "TRUE", sessionPool, 10);
This method accepts the following arguments: the queue on which to listen, a message selector, the session pool that must be associated with the consumer, and the maximum number of messages that can be assigned to each session simultaneously. As messages are delivered to the queue, the connection consumer will dole them out to each session, ensuring in each case that no session is loaded with more than 10 messages at one time. In this way, you can assign a pool of JMS sessions to multiple consumers, and concurrently handle messages arriving at different destinations.