org.springframework.jms.listener

## Class DefaultMessageListenerContainer

- java.lang.Object
- - org.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:
  org.springframework.beans.factory.Aware, org.springframework.beans.factory.BeanNameAware, org.springframework.beans.factory.DisposableBean, org.springframework.beans.factory.InitializingBean, org.springframework.context.Lifecycle, org.springframework.context.Phased, org.springframework.context.SmartLifecycle, MessageListenerContainer

    public class DefaultMessageListenerContainer
    extends AbstractPollingMessageListenerContainer

Message listener container variant that uses plain JMS client APIs, specifically a loop of `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 Java EE environment, with only minimal differences in configuration.

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 to 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 the broker is 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 `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 Java EE 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 by passing a Spring `PlatformTransactionManager` into the `"transactionManager"` property. This will usually be a `org.springframework.transaction.jta.JtaTransactionManager` in a Java EE environment, in combination with a JTA-aware JMS `ConnectionFactory` obtained from JNDI (check your Java EE server's documentation). Note that this listener container will automatically reobtain all JMS handles for each transaction in case an external transaction manager is specified, for compatibility with all Java EE 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 if an external transaction manager is involved.

Dynamic scaling of the number of concurrent invokers can be activated by 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, otherwise you'd receive the same message multiple times on the same node.

Note: Don't use Spring's `CachingConnectionFactory` in combination with dynamic scaling. Ideally, don't use it with a message listener container at all, since it is generally preferable to let the listener container itself handle appropriate caching within its lifecycle. Also, stopping and restarting a listener container will only work with an independent, locally cached Connection - not with an externally cached one.

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. Note that for the default "AUTO_ACKNOWLEDGE" mode, this container applies automatic message acknowledgment before listener execution, with no redelivery in case of an exception.

Since:
  2.0
Author:
  Juergen Hoeller
See Also:
  `AbstractPollingMessageListenerContainer.setTransactionManager(org.springframework.transaction.PlatformTransactionManager)`, `setCacheLevel(int)`, `MessageConsumer.receive(long)`, `SimpleMessageListenerContainer`, `JmsMessageEndpointManager`

### Nested Class Summary

### Nested classes/interfaces inherited from class org.springframework.jms.listener.AbstractJmsListeningContainer

`AbstractJmsListeningContainer.SharedConnectionNotInitializedException`

### Field Summary

Fields
`static int` `CACHE_AUTO` Constant that indicates automatic choice of an appropriate caching level (depending on the transaction management strategy).
`static int` `CACHE_CONNECTION` Constant that indicates to cache a shared JMS `Connection` for each listener thread.
`static int` `CACHE_CONSUMER` Constant that indicates to cache a shared JMS `Connection`, a JMS `Session`, and a JMS MessageConsumer for each listener thread.
`static int` `CACHE_NONE` Constant that indicates to cache no JMS resources at all.
`static int` `CACHE_SESSION` Constant that indicates to cache a shared JMS `Connection` and a JMS `Session` for each listener thread.
`static long` `DEFAULT_RECOVERY_INTERVAL` The default recovery interval: 5000 ms = 5 seconds.
`static String` `DEFAULT_THREAD_NAME_PREFIX` Default thread name prefix: "DefaultMessageListenerContainer-".

### Fields inherited from class org.springframework.jms.listener.AbstractPollingMessageListenerContainer

`DEFAULT_RECEIVE_TIMEOUT`

### Fields inherited from class org.springframework.jms.listener.AbstractJmsListeningContainer

`lifecycleMonitor, sharedConnectionMonitor`

### Fields inherited from class org.springframework.jms.support.destination.JmsDestinationAccessor

`RECEIVE_TIMEOUT_INDEFINITE_WAIT, RECEIVE_TIMEOUT_NO_WAIT`

### Fields inherited from class org.springframework.jms.support.JmsAccessor

`logger`

### Fields inherited from interface org.springframework.context.SmartLifecycle

`DEFAULT_PHASE`

### Constructor Summary

Constructors
Constructor and Description
`DefaultMessageListenerContainer()`

### Method Summary

All Methods Instance Methods Concrete Methods
`protected boolean` `applyBackOffTime(org.springframework.util.backoff.BackOffExecution execution)` Apply the next back-off time using the specified `BackOffExecution`.
`protected org.springframework.core.task.TaskExecutor` `createDefaultTaskExecutor()` Create a default TaskExecutor.
`protected void` `doInitialize()` Creates the specified number of concurrent consumers, in the form of a JMS Session plus associated MessageConsumer running in a separate thread.
`protected void` `doRescheduleTask(Object task)` Re-executes the given task via this listener container's TaskExecutor.
`protected void` `doShutdown()` Destroy the registered JMS Sessions and associated MessageConsumers.
`protected void` `establishSharedConnection()` Overridden to accept a failure in the initial setup - leaving it up to the asynchronous invokers to establish the shared Connection on first access.
`int` `getActiveConsumerCount()` Return the number of currently active consumers.
`int` `getCacheLevel()` Return the level of caching that this listener container is allowed to apply.
`int` `getConcurrentConsumers()` Return the "concurrentConsumer" setting.
`int` `getIdleConsumerLimit()` Return the limit for the number of idle consumers.
`int` `getIdleTaskExecutionLimit()` Return the limit for idle executions of a consumer task.
`int` `getMaxConcurrentConsumers()` Return the "maxConcurrentConsumer" setting.
`int` `getMaxMessagesPerTask()` Return the maximum number of messages to process in one task.
`int` `getScheduledConsumerCount()` Return the number of currently scheduled consumers.
`protected void` `handleListenerSetupFailure(Throwable ex, boolean alreadyRecovered)` Handle the given exception that arose during setup of a listener.
`void` `initialize()` Initialize this container.
`boolean` `isRecovering()` Return whether this listener container is currently in a recovery attempt.
`boolean` `isRegisteredWithDestination()` Return whether at least one consumer has entered a fixed registration with the target destination.
`protected void` `messageReceived(Object invoker, Session session)` Tries scheduling a new invoker, since we know messages are coming in...
`protected void` `noMessageReceived(Object invoker, Session session)` Marks the affected invoker as idle.
`protected void` `recoverAfterListenerSetupFailure()` Recover this listener container after a listener failed to set itself up, for example re-establishing the underlying Connection.
`protected void` `refreshConnectionUntilSuccessful()` Refresh the underlying Connection, not returning before an attempt has been successful.
`protected void` `refreshDestination()` Refresh the JMS destination that this listener container operates on.
`protected void` `scheduleNewInvokerIfAppropriate()` Schedule a new invoker, increasing the total number of scheduled invokers for this listener container, but only if the specified "maxConcurrentConsumers" limit has not been reached yet, and only if the specified "idleConsumerLimit" has not been reached either.
`void` `setBackOff(org.springframework.util.backoff.BackOff backOff)` Specify the `BackOff` instance to use to compute the interval between recovery attempts.
`void` `setCacheLevel(int cacheLevel)` Specify the level of caching that this listener container is allowed to apply.
`void` `setCacheLevelName(String constantName)` Specify the level of caching that this listener container is allowed to apply, in the form of the name of the corresponding constant: e.g.
`void` `setConcurrency(String concurrency)` Specify concurrency limits via a "lower-upper" String, e.g.
`void` `setConcurrentConsumers(int concurrentConsumers)` Specify the number of concurrent consumers to create.
`void` `setIdleConsumerLimit(int idleConsumerLimit)` Specify the limit for the number of consumers that are allowed to be idle at any given time.
`void` `setIdleTaskExecutionLimit(int idleTaskExecutionLimit)` Specify the limit for idle executions of a consumer task, not having received any message within its execution.
`void` `setMaxConcurrentConsumers(int maxConcurrentConsumers)` Specify the maximum number of concurrent consumers to create.
`void` `setMaxMessagesPerTask(int maxMessagesPerTask)` Specify the maximum number of messages to process in one task.
`void` `setRecoveryInterval(long recoveryInterval)` Specify the interval between recovery attempts, in milliseconds.
`void` `setTaskExecutor(Executor taskExecutor)` Set the Spring `TaskExecutor` to use for running the listener threads.
`protected boolean` `sharedConnectionEnabled()` Use a shared JMS Connection depending on the "cacheLevel" setting.
`void` `start()` Overridden to reset the stop callback, if any.
`protected void` `startSharedConnection()` This implementations proceeds even after an exception thrown from `Connection.start()`, relying on listeners to perform appropriate recovery.
`void` `stop(Runnable callback)` Stop this listener container, invoking the specific callback once all listener processing has actually stopped.
`protected void` `stopSharedConnection()` This implementations proceeds even after an exception thrown from `Connection.stop()`, relying on listeners to perform appropriate recovery after a restart.

### Methods inherited from class org.springframework.jms.listener.AbstractPollingMessageListenerContainer

`createListenerConsumer, doReceiveAndExecute, getConnection, getReceiveTimeout, getSession, getTransactionManager, isSessionLocallyTransacted, receiveAndExecute, receiveMessage, setReceiveTimeout, setSessionTransacted, setTransactionManager, setTransactionName, setTransactionTimeout, shouldCommitAfterNoMessageReceived`

### Methods inherited from class org.springframework.jms.listener.AbstractMessageListenerContainer

`checkMessageListener, commitIfNecessary, createConsumer, doExecuteListener, doInvokeListener, doInvokeListener, executeListener, getDefaultSubscriptionName, getDestination, getDestinationDescription, getDestinationName, getDurableSubscriptionName, getErrorHandler, getExceptionListener, getMessageConverter, getMessageListener, getMessageSelector, getReplyQosSettings, getSubscriptionName, handleListenerException, invokeErrorHandler, invokeExceptionListener, invokeListener, isAcceptMessagesWhileStopping, isExposeListenerSession, isPubSubNoLocal, isReplyPubSubDomain, isSubscriptionDurable, isSubscriptionShared, rollbackIfNecessary, rollbackOnExceptionIfNecessary, setAcceptMessagesWhileStopping, setDestination, setDestinationName, setDurableSubscriptionName, setErrorHandler, setExceptionListener, setExposeListenerSession, setMessageConverter, setMessageListener, setMessageSelector, setPubSubNoLocal, setReplyPubSubDomain, setReplyQosSettings, setSubscriptionDurable, setSubscriptionName, setSubscriptionShared, setupMessageListener, validateConfiguration`

### Methods inherited from class org.springframework.jms.listener.AbstractJmsListeningContainer

`afterPropertiesSet, createSharedConnection, destroy, doStart, doStop, getBeanName, getClientId, getPausedTaskCount, getPhase, getSharedConnection, isActive, isAutoStartup, isRunning, logRejectedTask, prepareSharedConnection, refreshSharedConnection, rescheduleTaskIfNecessary, resumePausedTasks, runningAllowed, setAutoStartup, setBeanName, setClientId, setPhase, shutdown, stop`

### Methods inherited from class org.springframework.jms.support.destination.JmsDestinationAccessor

`getDestinationResolver, isPubSubDomain, receiveFromConsumer, resolveDestinationName, setDestinationResolver, setPubSubDomain`

### Methods inherited from class org.springframework.jms.support.JmsAccessor

`convertJmsAccessException, createConnection, createSession, getConnectionFactory, getSessionAcknowledgeMode, isClientAcknowledge, isSessionTransacted, obtainConnectionFactory, setConnectionFactory, setSessionAcknowledgeMode, setSessionAcknowledgeModeName`

### Methods inherited from class java.lang.Object

`clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait`

### Methods inherited from interface org.springframework.jms.listener.MessageListenerContainer

`getDestinationResolver, isPubSubDomain`

### Methods inherited from interface org.springframework.context.SmartLifecycle

`getPhase, isAutoStartup`

### Methods inherited from interface org.springframework.context.Lifecycle

`isRunning, stop`

### Field Detail

#### DEFAULT_THREAD_NAME_PREFIX

    public static final String DEFAULT_THREAD_NAME_PREFIX

Default thread name prefix: "DefaultMessageListenerContainer-".

#### DEFAULT_RECOVERY_INTERVAL

    public static final long DEFAULT_RECOVERY_INTERVAL

The default recovery interval: 5000 ms = 5 seconds.

See Also:
  Constant Field Values

#### CACHE_NONE

    public static final int CACHE_NONE

Constant that indicates to cache no JMS resources at all.

See Also:
  `setCacheLevel(int)`, Constant Field Values

#### CACHE_CONNECTION

    public static final int CACHE_CONNECTION

Constant that indicates to cache a shared JMS `Connection` for each listener thread.

See Also:
  `setCacheLevel(int)`, Constant Field Values

#### CACHE_SESSION

    public static final int CACHE_SESSION

Constant that indicates to cache a shared JMS `Connection` and a JMS `Session` for each listener thread.

See Also:
  `setCacheLevel(int)`, Constant Field Values

#### CACHE_CONSUMER

    public static final int CACHE_CONSUMER

Constant that indicates to cache a shared JMS `Connection`, a JMS `Session`, and a JMS MessageConsumer for each listener thread.

See Also:
  `setCacheLevel(int)`, Constant Field Values

#### CACHE_AUTO

    public static final int CACHE_AUTO

Constant that indicates automatic choice of an appropriate caching level (depending on the transaction management strategy).

See Also:
  `setCacheLevel(int)`, Constant Field Values

### Constructor Detail

#### DefaultMessageListenerContainer

    public DefaultMessageListenerContainer()

### Method Detail

#### setTaskExecutor

    public void setTaskExecutor(Executor taskExecutor)

Set the Spring `TaskExecutor` to use for running the listener threads.

Default is a `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 Java EE environment. A plain thread pool does not add much value, as this listener container will occupy a number of threads for its entire lifetime.

See Also:
  `setConcurrentConsumers(int)`, `SimpleAsyncTaskExecutor`, `org.springframework.scheduling.commonj.WorkManagerTaskExecutor`

#### setBackOff

    public void setBackOff(org.springframework.util.backoff.BackOff backOff)

Specify the `BackOff` instance to use to compute the interval between recovery attempts. If the `BackOffExecution` implementation returns `BackOffExecution.STOP`, this listener container will not further attempt to recover.

The `recovery interval` is ignored when this property is set.

Since:
  4.1

#### setRecoveryInterval

    public void setRecoveryInterval(long recoveryInterval)

Specify the interval between recovery attempts, in milliseconds. The default is 5000 ms, that is, 5 seconds. This is a convenience method to create a `FixedBackOff` with the specified interval.

For more recovery options, consider specifying a `BackOff` instance instead.

See Also:
  `setBackOff(BackOff)`, `handleListenerSetupFailure(java.lang.Throwable, boolean)`

#### setCacheLevelName

    public void setCacheLevelName(String constantName)
                           throws IllegalArgumentException

Specify the level of caching that this listener container is allowed to apply, in the form of the name of the corresponding constant: e.g. "CACHE_CONNECTION".

Throws:
  `IllegalArgumentException`
See Also:
  `setCacheLevel(int)`

#### setCacheLevel

    public void setCacheLevel(int cacheLevel)

Specify the level of caching that this listener container is allowed to apply.

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` otherwise (operating with local JMS resources).

Some Java EE 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 by default does not cache any of those. However, depending on the rules of your server with respect to the caching of transactional resources, consider switching this setting to at least `CACHE_CONNECTION` or `CACHE_SESSION` even in conjunction with an external transaction manager.

See Also:
  `CACHE_NONE`, `CACHE_CONNECTION`, `CACHE_SESSION`, `CACHE_CONSUMER`, `setCacheLevelName(java.lang.String)`, `AbstractPollingMessageListenerContainer.setTransactionManager(org.springframework.transaction.PlatformTransactionManager)`

#### getCacheLevel

    public int getCacheLevel()

Return the level of caching that this listener container is allowed to apply.

#### setConcurrency

    public void setConcurrency(String concurrency)

Specify concurrency limits via a "lower-upper" String, e.g. "5-10", or a simple upper limit String, e.g. "10" (the lower limit will be 1 in this case).

This listener container will always hold on to the minimum number of consumers (`setConcurrentConsumers(int)`) and will slowly scale up to the maximum number of consumers `setMaxConcurrentConsumers(int)` in case of increasing load.

Specified by:
  `setConcurrency` in class `AbstractMessageListenerContainer`

#### setConcurrentConsumers

    public void setConcurrentConsumers(int concurrentConsumers)

Specify the number of concurrent consumers to create. Default is 1.

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, unless vendor-specific setup measures clearly allow for it. With regular setup, 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.

See Also:
  `setMaxConcurrentConsumers(int)`

#### getConcurrentConsumers

    public final int getConcurrentConsumers()

Return the "concurrentConsumer" setting.

This returns the currently configured "concurrentConsumers" value; the number of currently scheduled/active consumers might differ.

See Also:
  `getScheduledConsumerCount()`, `getActiveConsumerCount()`

#### setMaxConcurrentConsumers

    public void setMaxConcurrentConsumers(int maxConcurrentConsumers)

Specify the maximum number of concurrent consumers to create. Default is 1.

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, unless vendor-specific setup measures clearly allow for it. With regular setup, 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.

See Also:
  `setConcurrentConsumers(int)`

#### getMaxConcurrentConsumers

    public final int getMaxConcurrentConsumers()

Return the "maxConcurrentConsumer" setting.

This returns the currently configured "maxConcurrentConsumers" value; the number of currently scheduled/active consumers might differ.

See Also:
  `getScheduledConsumerCount()`, `getActiveConsumerCount()`

#### setMaxMessagesPerTask

    public void setMaxMessagesPerTask(int maxMessagesPerTask)

Specify the maximum number of messages to process in one task. More concretely, this limits the number of message reception attempts per task, which includes receive iterations that did not actually pick up a message until they hit their timeout (see the `"receiveTimeout"` property).

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.

See Also:
  `setTaskExecutor(java.util.concurrent.Executor)`, `AbstractPollingMessageListenerContainer.setReceiveTimeout(long)`, `SchedulingTaskExecutor.prefersShortLivedTasks()`

#### getMaxMessagesPerTask

    public final int getMaxMessagesPerTask()

Return the maximum number of messages to process in one task.

#### setIdleConsumerLimit

    public void setIdleConsumerLimit(int idleConsumerLimit)

Specify the limit for the number of consumers that are allowed to be idle at any given time.

This limit is used by the `scheduleNewInvokerIfAppropriate()` method to determine if a new invoker should be created. Increasing the limit causes invokers to be created more aggressively. This can be useful to ramp up the number of invokers faster.

The default is 1, only scheduling a new invoker (which is likely to be idle initially) if none of the existing invokers is currently idle.

#### getIdleConsumerLimit

    public final int getIdleConsumerLimit()

Return the limit for the number of idle consumers.

#### setIdleTaskExecutionLimit

    public void setIdleTaskExecutionLimit(int idleTaskExecutionLimit)

Specify the limit for idle executions of a consumer task, not having received any message within its execution. If this limit is reached, the task will shut down and leave receiving to other executing tasks.

The 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.

See Also:
  `setMaxMessagesPerTask(int)`, `AbstractPollingMessageListenerContainer.setReceiveTimeout(long)`

#### getIdleTaskExecutionLimit

    public final int getIdleTaskExecutionLimit()

Return the limit for idle executions of a consumer task.

#### initialize

    public void initialize()

Description copied from class: `AbstractJmsListeningContainer`
Initialize this container.

Creates a JMS Connection, starts the `Connection` (if `"autoStartup"` hasn't been turned off), and calls `AbstractJmsListeningContainer.doInitialize()`.

Overrides:
  `initialize` in class `AbstractPollingMessageListenerContainer`

#### doInitialize

    protected void doInitialize()
                         throws JMSException

Creates the specified number of concurrent consumers, in the form of a JMS Session plus associated MessageConsumer running in a separate thread.

Specified by:
  `doInitialize` in class `AbstractJmsListeningContainer`
Throws:
  `JMSException` - if registration failed
See Also:
  `scheduleNewInvoker()`, `setTaskExecutor(java.util.concurrent.Executor)`

#### doShutdown

    protected void doShutdown()
                       throws JMSException

Destroy the registered JMS Sessions and associated MessageConsumers.

Specified by:
  `doShutdown` in class `AbstractJmsListeningContainer`
Throws:
  `JMSException` - if shutdown failed
See Also:
  `AbstractJmsListeningContainer.shutdown()`

#### start

    public void start()
               throws JmsException

Overridden to reset the stop callback, if any.

Specified by:
  `start` in interface `org.springframework.context.Lifecycle`
Overrides:
  `start` in class `AbstractJmsListeningContainer`
Throws:
  `JmsException` - if starting failed
See Also:
  `AbstractJmsListeningContainer.doStart()`

#### stop

    public void stop(Runnable callback)
              throws JmsException

Stop this listener container, invoking the specific callback once all listener processing has actually stopped.

Note: Further `stop(runnable)` calls (before processing has actually stopped) will override the specified callback. Only the latest specified callback will be invoked.

If a subsequent `start()` call restarts the listener container before it has fully stopped, the callback will not get invoked at all.

Parameters:
  `callback` - the callback to invoke once listener processing has fully stopped
Throws:
  `JmsException` - if stopping failed
See Also:
  `AbstractJmsListeningContainer.stop()`

#### getScheduledConsumerCount

    public final int getScheduledConsumerCount()

Return the number of currently scheduled consumers.

This number will always be between "concurrentConsumers" and "maxConcurrentConsumers", but might be higher than "activeConsumerCount" (in case some consumers are scheduled but not executing at the moment).

See Also:
  `getConcurrentConsumers()`, `getMaxConcurrentConsumers()`, `getActiveConsumerCount()`

#### getActiveConsumerCount

    public final int getActiveConsumerCount()

Return the number of currently active consumers.

This number will always be between "concurrentConsumers" and "maxConcurrentConsumers", but might be lower than "scheduledConsumerCount" (in case some consumers are scheduled but not executing at the moment).

See Also:
  `getConcurrentConsumers()`, `getMaxConcurrentConsumers()`, `getActiveConsumerCount()`

#### isRegisteredWithDestination

    public boolean isRegisteredWithDestination()

Return whether at least one consumer has entered a fixed registration with the target destination. This is particularly interesting for the pub-sub case where it might be important to have an actual consumer registered that is guaranteed not to miss any messages that are just about to be published.

This method may be polled after a `start()` call, until asynchronous registration of consumers has happened which is when the method will start returning `true` – provided that the listener container ever actually establishes a fixed registration. It will then keep returning `true` until shutdown, since the container will hold on to at least one consumer registration thereafter.

Note that a listener container is not bound to having a fixed registration in the first place. It may also keep recreating consumers for every invoker execution. This particularly depends on the `cache level` setting: only `CACHE_CONSUMER` will lead to a fixed registration.

#### createDefaultTaskExecutor

    protected org.springframework.core.task.TaskExecutor createDefaultTaskExecutor()

Create a default TaskExecutor. Called if no explicit TaskExecutor has been specified.

The default implementation builds a `SimpleAsyncTaskExecutor` with the specified bean name (or the class name, if no bean name specified) as thread name prefix.

See Also:
  `SimpleAsyncTaskExecutor.SimpleAsyncTaskExecutor(String)`

#### sharedConnectionEnabled

    protected final boolean sharedConnectionEnabled()

Use a shared JMS Connection depending on the "cacheLevel" setting.

Specified by:
  `sharedConnectionEnabled` in class `AbstractJmsListeningContainer`
See Also:
  `setCacheLevel(int)`, `CACHE_CONNECTION`

#### doRescheduleTask

    protected void doRescheduleTask(Object task)

Re-executes the given task via this listener container's TaskExecutor.

Overrides:
  `doRescheduleTask` in class `AbstractJmsListeningContainer`
Parameters:
  `task` - the task object to reschedule
See Also:
  `setTaskExecutor(java.util.concurrent.Executor)`

#### messageReceived

    protected void messageReceived(Object invoker,
                                   Session session)

Tries scheduling a new invoker, since we know messages are coming in...

Overrides:
  `messageReceived` in class `AbstractPollingMessageListenerContainer`
Parameters:
  `invoker` - the invoker object (passed through)
  `session` - the receiving JMS Session
See Also:
  `scheduleNewInvokerIfAppropriate()`

#### noMessageReceived

    protected void noMessageReceived(Object invoker,
                                     Session session)

Marks the affected invoker as idle.

Overrides:
  `noMessageReceived` in class `AbstractPollingMessageListenerContainer`
Parameters:
  `invoker` - the invoker object (passed through)
  `session` - the receiving JMS Session

#### scheduleNewInvokerIfAppropriate

    protected void scheduleNewInvokerIfAppropriate()

Schedule a new invoker, increasing the total number of scheduled invokers for this listener container, but only if the specified "maxConcurrentConsumers" limit has not been reached yet, and only if the specified "idleConsumerLimit" has not been reached either.

Called once a message has been received, in order to scale up while processing the message in the invoker that originally received it.

See Also:
  `setTaskExecutor(java.util.concurrent.Executor)`, `getMaxConcurrentConsumers()`, `getIdleConsumerLimit()`

#### establishSharedConnection

    protected void establishSharedConnection()

Overridden to accept a failure in the initial setup - leaving it up to the asynchronous invokers to establish the shared Connection on first access.

Overrides:
  `establishSharedConnection` in class `AbstractJmsListeningContainer`
See Also:
  `refreshConnectionUntilSuccessful()`

#### startSharedConnection

    protected void startSharedConnection()

This implementations proceeds even after an exception thrown from `Connection.start()`, relying on listeners to perform appropriate recovery.

Overrides:
  `startSharedConnection` in class `AbstractJmsListeningContainer`
See Also:
  `Connection.start()`

#### stopSharedConnection

    protected void stopSharedConnection()

This implementations proceeds even after an exception thrown from `Connection.stop()`, relying on listeners to perform appropriate recovery after a restart.

Overrides:
  `stopSharedConnection` in class `AbstractJmsListeningContainer`
See Also:
  `Connection.start()`

#### handleListenerSetupFailure

    protected void handleListenerSetupFailure(Throwable ex,
                                              boolean alreadyRecovered)

Handle the given exception that arose during setup of a listener. Called for every such exception in every concurrent listener.

The default implementation logs the exception at warn level if not recovered yet, and at debug level if already recovered. Can be overridden in subclasses.

Parameters:
  `ex` - the exception to handle
  `alreadyRecovered` - whether a previously executing listener already recovered from the present listener setup failure (this usually indicates a follow-up failure than can be ignored other than for debug log purposes)
See Also:
  `recoverAfterListenerSetupFailure()`

#### recoverAfterListenerSetupFailure

    protected void recoverAfterListenerSetupFailure()

Recover this listener container after a listener failed to set itself up, for example re-establishing the underlying Connection.

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.

See Also:
  `refreshConnectionUntilSuccessful()`, `refreshDestination()`

#### refreshConnectionUntilSuccessful

    protected void refreshConnectionUntilSuccessful()

Refresh the underlying Connection, not returning before an attempt has been successful. Called in case of a shared Connection as well as without shared Connection, so either needs to operate on the shared Connection or on a temporary Connection that just gets established for validation purposes.

The default implementation retries until it successfully established a Connection, for as long as this message listener container is running. Applies the specified recovery interval between retries.

See Also:
  `setRecoveryInterval(long)`, `start()`, `AbstractJmsListeningContainer.stop()`

#### refreshDestination

    protected void refreshDestination()

Refresh the JMS destination that this listener container operates on.

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.

See Also:
  `AbstractMessageListenerContainer.setDestinationName(java.lang.String)`, `CachingDestinationResolver`

#### applyBackOffTime

    protected boolean applyBackOffTime(org.springframework.util.backoff.BackOffExecution execution)

Apply the next back-off time using the specified `BackOffExecution`.

Return `true` if the back-off period has been applied and a new attempt to recover should be made, `false` if no further attempt should be made.

Since:
  4.1

#### isRecovering

    public final boolean isRecovering()

Return whether this listener container is currently in a recovery attempt.

May be used to detect recovery phases but also the end of a recovery phase, with `isRecovering()` switching to `false` after having been found to return `true` before.

See Also:
  `recoverAfterListenerSetupFailure()`