java.lang.Objectorg.springframework.jms.support.JmsAccessor
org.springframework.jms.support.destination.JmsDestinationAccessor
org.springframework.jms.listener.AbstractJmsListeningContainer
org.springframework.jms.listener.AbstractMessageListenerContainer
org.springframework.jms.listener.AbstractPollingMessageListenerContainer
org.springframework.jms.listener.DefaultMessageListenerContainer
All Implemented Interfaces:
BeanNameAware, DisposableBean, Lifecycle, InitializingBean
Direct Known Subclasses:
DefaultMessageListenerContainer102
MessageConsumer.receive() calls that also allow for
transactional reception of messages (registering them with XA transactions).
Designed to work in a native JMS environment as well as in a J2EE environment,
with only minimal differences in configuration.
NOTE: This class requires a JMS 1.1+ provider, because it builds on the domain-independent API. Use the DefaultMessageListenerContainer102 subclass for a JMS 1.0.2 provider, e.g. when running on a J2EE 1.3 server.
This is a simple but nevertheless powerful form of message listener container. On startup, it obtains a fixed number of JMS Sessions to invoke the listener, and optionally allows for dynamic adaptation at runtime (up until a maximum number). Like SimpleMessageListenerContainer , its main advantage is its low level of runtime complexity, in particular the minimal requirements on the JMS provider: Not even the JMS ServerSessionPool facility is required. Beyond that, it is fully self-recovering in case of the broker being temporarily unavailable, and allows for stops/restarts as well as runtime changes to its configuration.
Actual MessageListener execution happens in asynchronous work units which are created through Spring's org.springframework.core.task.TaskExecutor abstraction. By default, the specified number of invoker tasks will be created on startup, according to the "concurrentConsumers" setting. Specify an alternative TaskExecutor to integrate with an existing thread pool facility (such as a J2EE server's), for example using a CommonJ WorkManager . With a native JMS setup, each of those listener threads is going to use a cached JMS Session and MessageConsumer (only refreshed in case of failure), using the JMS provider's resources as efficiently as possible.
Message reception and listener execution can automatically be wrapped in transactions through passing a Spring org.springframework.transaction.PlatformTransactionManager into the "transactionManager" property. This will usually be a org.springframework.transaction.jta.JtaTransactionManager in a J2EE enviroment, in combination with a JTA-aware JMS ConnectionFactory obtained from JNDI (check your J2EE server's documentation). Note that this listener container will automatically reobtain all JMS handles for each transaction in case of an external transaction manager specified, for compatibility with all J2EE servers (in particular JBoss). This non-caching behavior can be overridden through the "cacheLevel" / "cacheLevelName" property, enforcing caching of the Connection (or also Session and MessageConsumer) even in case of an external transaction manager being involved.
Dynamic scaling of the number of concurrent invokers can be activated through specifying a "maxConcurrentConsumers" value that is higher than the "concurrentConsumers" value. Since the latter's default is 1, you can also simply specify a "maxConcurrentConsumers" of e.g. 5, which will lead to dynamic scaling up to 5 concurrent consumers in case of increasing message load, as well as dynamic shrinking back to the standard number of consumers once the load decreases. Consider adapting the "idleTaskExecutionLimit" setting to control the lifespan of each new task, to avoid frequent scaling up and down, in particular if the ConnectionFactory does not pool JMS Sessions and/or the TaskExecutor does not pool threads (check your configuration!). Note that dynamic scaling only really makes sense for a queue in the first place; for a topic, you will typically stick with the default number of 1 consumer, else you'd receive the same message multiple times on the same node.
It is strongly recommended to either set "sessionTransacted" to "true" or specify an external "transactionManager" . See the AbstractMessageListenerContainer javadoc for details on acknowledge modes and native transaction options, as well as the AbstractPollingMessageListenerContainer javadoc for details on configuring an external transaction manager.
Juergen - Hoeller2.0 - | Field Summary | ||
|---|---|---|
| public static final String | DEFAULT_THREAD_NAME_PREFIX | Default thread name prefix: "DefaultMessageListenerContainer-". |
| public static final long | DEFAULT_RECOVERY_INTERVAL | The default recovery interval: 5000 ms = 5 seconds. |
| public static final int | CACHE_NONE | Constant that indicates to cache no JMS resources at all.
|
| public static final int | CACHE_CONNECTION | Constant that indicates to cache a shared JMS Connection.
|
| public static final int | CACHE_SESSION | Constant that indicates to cache a shared JMS Connection
and a JMS Session for each listener thread.
|
| public static final int | CACHE_CONSUMER | Constant that indicates to cache a shared JMS Connection
and a JMS Session for each listener thread, as well as
a JMS MessageConsumer for each listener thread.
|
| public static final int | CACHE_AUTO | Constant that indicates automatic choice of an appropriate
caching level (depending on the transaction management strategy).
|
| Fields inherited from org.springframework.jms.listener.AbstractPollingMessageListenerContainer: |
|---|
| DEFAULT_RECEIVE_TIMEOUT |
| Fields inherited from org.springframework.jms.listener.AbstractJmsListeningContainer: |
|---|
| sharedConnectionMonitor, lifecycleMonitor |
| Fields inherited from org.springframework.jms.support.JmsAccessor: |
|---|
| logger |
| Methods from org.springframework.jms.listener.AbstractPollingMessageListenerContainer: |
|---|
| createConsumer, createListenerConsumer, doReceiveAndExecute, getConnection, getSession, getTransactionManager, initialize, isPubSubNoLocal, isSessionLocallyTransacted, messageReceived, noMessageReceived, receiveAndExecute, receiveMessage, setPubSubNoLocal, setReceiveTimeout, setSessionTransacted, setTransactionManager, setTransactionName, setTransactionTimeout |
| Methods from org.springframework.jms.listener.AbstractJmsListeningContainer: |
|---|
| afterPropertiesSet, createSharedConnection, destroy, doInitialize, doRescheduleTask, doShutdown, doStart, doStop, establishSharedConnection, getBeanName, getClientId, getPausedTaskCount, getSharedConnection, initialize, isActive, isRunning, logRejectedTask, prepareSharedConnection, refreshSharedConnection, rescheduleTaskIfNecessary, resumePausedTasks, runningAllowed, setAutoStartup, setBeanName, setClientId, sharedConnectionEnabled, shutdown, start, startSharedConnection, stop, stopSharedConnection, validateConfiguration |
| Methods from org.springframework.jms.support.destination.JmsDestinationAccessor: |
|---|
| getDestinationResolver, isPubSubDomain, resolveDestinationName, setDestinationResolver, setPubSubDomain |
| Methods from org.springframework.jms.support.JmsAccessor: |
|---|
| afterPropertiesSet, convertJmsAccessException, createConnection, createSession, getConnectionFactory, getSessionAcknowledgeMode, isClientAcknowledge, isSessionTransacted, setConnectionFactory, setSessionAcknowledgeMode, setSessionAcknowledgeModeName, setSessionTransacted |
| Methods from java.lang.Object: |
|---|
| equals, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait |
| Method from org.springframework.jms.listener.DefaultMessageListenerContainer Detail: |
|---|
The default implementation builds a org.springframework.core.task.SimpleAsyncTaskExecutor with the specified bean name (or the class name, if no bean name specified) as thread name prefix. |
|
|
|
|
This number will always be inbetween "concurrentConsumers" and "maxConcurrentConsumers", but might be lower than "scheduledConsumerCount". (in case of some consumers being scheduled but not executed at the moment). |
|
This returns the currently configured "concurrentConsumers" value; the number of currently scheduled/active consumers might differ. |
|
This returns the currently configured "maxConcurrentConsumers" value; the number of currently scheduled/active consumers might differ. |
|
This number will always be inbetween "concurrentConsumers" and "maxConcurrentConsumers", but might be higher than "activeConsumerCount" (in case of some consumers being scheduled but not executed at the moment). |
The default implementation logs the exception at error level if not recovered yet, and at debug level if already recovered. Can be overridden in subclasses. |
|
|
|
The default implementation delegates to DefaultMessageListenerContainer's recovery-capable #refreshConnectionUntilSuccessful() method, which will try to re-establish a Connection to the JMS provider both for the shared and the non-shared Connection case. |
The default implementation retries until it successfully established a Connection, for as long as this message listener container is active. Applies the specified recovery interval between retries. |
Called after listener setup failure, assuming that a cached Destination object might have become invalid (a typical case on WebLogic JMS). The default implementation removes the destination from a DestinationResolver's cache, in case of a CachingDestinationResolver. |
Called once a message has been received, to scale up while processing the message in the invoker that originally received it. |
Default is CACHE_NONE if an external transaction manager has been specified (to reobtain all resources freshly within the scope of the external transaction), and CACHE_CONSUMER else (operating with local JMS resources). Some J2EE servers only register their JMS resources with an ongoing XA transaction in case of a freshly obtained JMS Connection and Session, which is why this listener container does by default not cache any of those. However, if you want to optimize for a specific server, consider switching this setting to at least CACHE_CONNECTION or CACHE_SESSION even in conjunction with an external transaction manager. Currently known servers that absolutely require CACHE_NONE for XA transaction processing: JBoss 4. For any others, consider raising the cache level. |
|
Specifying a higher value for this setting will increase the standard level of scheduled concurrent consumers at runtime: This is effectively the minimum number of concurrent consumers which will be scheduled at any given time. This is a static setting; for dynamic scaling, consider specifying the "maxConcurrentConsumers" setting instead. Raising the number of concurrent consumers is recommendable in order to scale the consumption of messages coming in from a queue. However, note that any ordering guarantees are lost once multiple consumers are registered. In general, stick with 1 consumer for low-volume queues. Do not raise the number of concurrent consumers for a topic. This would lead to concurrent consumption of the same message, which is hardly ever desirable. This setting can be modified at runtime, for example through JMX. |
Default is 1, closing idle resources early once a task didn't receive a message. This applies to dynamic scheduling only; see the "maxConcurrentConsumers" setting. The minimum number of consumers (see "concurrentConsumers" ) will be kept around until shutdown in any case. Within each task execution, a number of message reception attempts (according to the "maxMessagesPerTask" setting) will each wait for an incoming message (according to the "receiveTimeout" setting). If all of those receive attempts in a given task return without a message, the task is considered idle with respect to received messages. Such a task may still be rescheduled; however, once it reached the specified "idleTaskExecutionLimit", it will shut down (in case of dynamic scaling). Raise this limit if you encounter too frequent scaling up and down. With this limit being higher, an idle consumer will be kept around longer, avoiding the restart of a consumer once a new load of messages comes in. Alternatively, specify a higher "maxMessagesPerTask" and/or "receiveTimeout" value, which will also lead to idle consumers being kept around for a longer time (while also increasing the average execution time of each scheduled task). This setting can be modified at runtime, for example through JMX. |
If this setting is higher than "concurrentConsumers", the listener container will dynamically schedule new consumers at runtime, provided that enough incoming messages are encountered. Once the load goes down again, the number of consumers will be reduced to the standard level ("concurrentConsumers") again. Raising the number of concurrent consumers is recommendable in order to scale the consumption of messages coming in from a queue. However, note that any ordering guarantees are lost once multiple consumers are registered. In general, stick with 1 consumer for low-volume queues. Do not raise the number of concurrent consumers for a topic. This would lead to concurrent consumption of the same message, which is hardly ever desirable. This setting can be modified at runtime, for example through JMX. |
Default is unlimited (-1) in case of a standard TaskExecutor, reusing the original invoker threads until shutdown (at the expense of limited dynamic scheduling). In case of a SchedulingTaskExecutor indicating a preference for short-lived tasks, the default is 10 instead. Specify a number of 10 to 100 messages to balance between rather long-lived and rather short-lived tasks here. Long-lived tasks avoid frequent thread context switches through sticking with the same thread all the way through, while short-lived tasks allow thread pools to control the scheduling. Hence, thread pools will usually prefer short-lived tasks. This setting can be modified at runtime, for example through JMX. |
|
Default is a org.springframework.core.task.SimpleAsyncTaskExecutor , starting up a number of new threads, according to the specified number of concurrent consumers. Specify an alternative TaskExecutor for integration with an existing thread pool. Note that this really only adds value if the threads are managed in a specific fashion, for example within a J2EE environment. A plain thread pool does not add much value, as this listener container will occupy a number of threads for its entire lifetime. |
|
|
|
Connection.start(), relying on listeners to perform
appropriate recovery. |
Note: Further If a subsequent #start() call restarts the listener container before it has fully stopped, the callback will not get invoked at all. |
Connection.stop(), relying on listeners to perform
appropriate recovery after a restart. |
|