org.springframework.jms.listener

## Class AbstractJmsListeningContainer

- java.lang.Object
- - org.springframework.jms.support.JmsAccessor
  - - org.springframework.jms.support.destination.JmsDestinationAccessor
    - - org.springframework.jms.listener.AbstractJmsListeningContainer

- All Implemented Interfaces:
    Aware, BeanNameAware, DisposableBean, InitializingBean, Lifecycle, Phased, SmartLifecycle
  Direct Known Subclasses:
    AbstractMessageListenerContainer

      public abstract class AbstractJmsListeningContainer
      extends JmsDestinationAccessor
      implements SmartLifecycle, BeanNameAware, DisposableBean

  Common base class for all containers which need to implement listening based on a JMS Connection (either shared or freshly obtained for each attempt). Inherits basic Connection and Session configuration handling from the `JmsAccessor` base class.

  This class provides basic lifecycle management, in particular management of a shared JMS Connection. Subclasses are supposed to plug into this lifecycle, implementing the `sharedConnectionEnabled()` as well as the `doInitialize()` and `doShutdown()` template methods.

  This base class does not assume any specific listener programming model or listener invoker mechanism. It just provides the general runtime lifecycle management needed for any kind of JMS-based listening mechanism that operates on a JMS Connection/Session.

  For a concrete listener programming model, check out the `AbstractMessageListenerContainer` subclass. For a concrete listener invoker mechanism, check out the `DefaultMessageListenerContainer` class.

  Since:
    2.0.3
  Author:
    Juergen Hoeller
  See Also:
    `sharedConnectionEnabled()`, `doInitialize()`, `doShutdown()`

- - ### Nested Class Summary

    Nested Classes
    Modifier and Type | Class and Description
    --- | ---
    `static class` | `AbstractJmsListeningContainer.SharedConnectionNotInitializedException` Exception that indicates that the initial setup of this container's shared JMS Connection failed.

  - ### Field Summary

    Fields
    Modifier and Type | Field and Description
    --- | ---
    `protected Object` | `lifecycleMonitor`
    `protected Object` | `sharedConnectionMonitor`

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

      `logger`

  - ### Constructor Summary

    Constructors
    Constructor and Description
    `AbstractJmsListeningContainer()`

  - ### Method Summary

    Methods
    Modifier and Type | Method and Description
    --- | ---
    `void` | `afterPropertiesSet()` Delegates to `validateConfiguration()` and `initialize()`.
    `protected Connection` | `createSharedConnection()` Create a shared Connection for this container.
    `void` | `destroy()` Calls `shutdown()` when the BeanFactory destroys the container instance.
    `protected abstract void` | `doInitialize()` Register any invokers within this container.
    `protected void` | `doRescheduleTask(Object task)` Reschedule the given task object immediately.
    `protected abstract void` | `doShutdown()` Close the registered invokers.
    `protected void` | `doStart()` Start the shared Connection, if any, and notify all invoker tasks.
    `protected void` | `doStop()` Notify all invoker tasks and stop the shared Connection, if any.
    `protected void` | `establishSharedConnection()` Establish a shared Connection for this container.
    `protected String` | `getBeanName()` Return the bean name that this listener container has been assigned in its containing bean factory, if any.
    `String` | `getClientId()` Return the JMS client ID for the shared Connection created and used by this container, if any.
    `int` | `getPausedTaskCount()` Determine the number of currently paused tasks, if any.
    `int` | `getPhase()` Return the phase in which this container will be started and stopped.
    `protected Connection` | `getSharedConnection()` Return the shared JMS Connection maintained by this container.
    `void` | `initialize()` Initialize this container.
    `boolean` | `isActive()` Return whether this container is currently active, that is, whether it has been set up but not shut down yet.
    `boolean` | `isAutoStartup()` Return whether this Lifecycle component should be started automatically by the container when the ApplicationContext is refreshed.
    `boolean` | `isRunning()` Determine whether this container is currently running, that is, whether it has been started and not stopped yet.
    `protected void` | `logRejectedTask(Object task, RuntimeException ex)` Log a task that has been rejected by `doRescheduleTask(java.lang.Object)`.
    `protected void` | `prepareSharedConnection(Connection connection)` Prepare the given Connection, which is about to be registered as shared Connection for this container.
    `protected void` | `refreshSharedConnection()` Refresh the shared Connection that this container holds.
    `protected boolean` | `rescheduleTaskIfNecessary(Object task)` Take the given task object and reschedule it, either immediately if this container is currently running, or later once this container has been restarted.
    `protected void` | `resumePausedTasks()` Try to resume all paused tasks.
    `protected boolean` | `runningAllowed()` Check whether this container's listeners are generally allowed to run.
    `void` | `setAutoStartup(boolean autoStartup)` Set whether to automatically start the container after initialization.
    `void` | `setBeanName(String beanName)` Set the name of the bean in the bean factory that created this bean.
    `void` | `setClientId(String clientId)` Specify the JMS client ID for a shared Connection created and used by this container.
    `void` | `setPhase(int phase)` Specify the phase in which this container should be started and stopped.
    `protected abstract boolean` | `sharedConnectionEnabled()` Return whether a shared JMS Connection should be maintained by this container base class.
    `void` | `shutdown()` Stop the shared Connection, call `doShutdown()`, and close this container.
    `void` | `start()` Start this container.
    `protected void` | `startSharedConnection()` Start the shared Connection.
    `void` | `stop()` Stop this container.
    `void` | `stop(Runnable callback)` Indicates that a Lifecycle component must stop if it is currently running.
    `protected void` | `stopSharedConnection()` Stop the shared Connection.
    `protected void` | `validateConfiguration()` Validate the configuration of this container.

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

      `getDestinationResolver, isPubSubDomain, resolveDestinationName, setDestinationResolver, setPubSubDomain`

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

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

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

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

- - ### Field Detail

    - #### sharedConnectionMonitor

          protected final Object sharedConnectionMonitor

    - #### lifecycleMonitor

          protected final Object lifecycleMonitor

  - ### Constructor Detail

    - #### AbstractJmsListeningContainer

          public AbstractJmsListeningContainer()

  - ### Method Detail

    - #### setClientId

          public void setClientId(String clientId)

      Specify the JMS client ID for a shared Connection created and used by this container.

      Note that client IDs need to be unique among all active Connections of the underlying JMS provider. Furthermore, a client ID can only be assigned if the original ConnectionFactory hasn't already assigned one.

      See Also:
        `Connection.setClientID(java.lang.String)`, `JmsAccessor.setConnectionFactory(javax.jms.ConnectionFactory)`

    - #### getClientId

          public String getClientId()

      Return the JMS client ID for the shared Connection created and used by this container, if any.

    - #### setAutoStartup

          public void setAutoStartup(boolean autoStartup)

      Set whether to automatically start the container after initialization.

      Default is "true"; set this to "false" to allow for manual startup through the `start()` method.

    - #### isAutoStartup

          public boolean isAutoStartup()

      Description copied from interface: `SmartLifecycle`
      Return whether this Lifecycle component should be started automatically by the container when the ApplicationContext is refreshed. A value of "false" indicates that the component is intended to be started manually.
      Specified by:
        `isAutoStartup` in interface `SmartLifecycle`

    - #### setPhase

          public void setPhase(int phase)

      Specify the phase in which this container should be started and stopped. The startup order proceeds from lowest to highest, and the shutdown order is the reverse of that. By default this value is Integer.MAX_VALUE meaning that this container starts as late as possible and stops as soon as possible.

    - #### getPhase

          public int getPhase()

      Return the phase in which this container will be started and stopped.
      Specified by:
        `getPhase` in interface `Phased`

    - #### setBeanName

          public void setBeanName(String beanName)

      Description copied from interface: `BeanNameAware`
      Set the name of the bean in the bean factory that created this bean.

      Invoked after population of normal bean properties but before an init callback such as `InitializingBean.afterPropertiesSet()` or a custom init-method.

      Specified by:
        `setBeanName` in interface `BeanNameAware`
      Parameters:
        `beanName` - the name of the bean in the factory. Note that this name is the actual bean name used in the factory, which may differ from the originally specified name: in particular for inner bean names, the actual bean name might have been made unique through appending "#..." suffixes. Use the `BeanFactoryUtils.originalBeanName(String)` method to extract the original bean name (without suffix), if desired.

    - #### getBeanName

          protected final String getBeanName()

      Return the bean name that this listener container has been assigned in its containing bean factory, if any.

    - #### afterPropertiesSet

          public void afterPropertiesSet()

      Delegates to `validateConfiguration()` and `initialize()`.
      Specified by:
        `afterPropertiesSet` in interface `InitializingBean`
      Overrides:
        `afterPropertiesSet` in class `JmsAccessor`

    - #### validateConfiguration

          protected void validateConfiguration()

      Validate the configuration of this container.

      The default implementation is empty. To be overridden in subclasses.

    - #### destroy

          public void destroy()

      Calls `shutdown()` when the BeanFactory destroys the container instance.
      Specified by:
        `destroy` in interface `DisposableBean`
      See Also:
        `shutdown()`

    - #### initialize

          public void initialize()
                          throws JmsException

      Initialize this container.

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

      Throws:
        `JmsException` - if startup failed

    - #### shutdown

          public void shutdown()
                        throws JmsException

      Stop the shared Connection, call `doShutdown()`, and close this container.
      Throws:
        `JmsException` - if shutdown failed

    - #### isActive

          public final boolean isActive()

      Return whether this container is currently active, that is, whether it has been set up but not shut down yet.

    - #### start

          public void start()
                     throws JmsException

      Start this container.
      Specified by:
        `start` in interface `Lifecycle`
      Throws:
        `JmsException` - if starting failed
      See Also:
        `doStart()`

    - #### doStart

          protected void doStart()
                          throws JMSException

      Start the shared Connection, if any, and notify all invoker tasks.
      Throws:
        `JMSException` - if thrown by JMS API methods
      See Also:
        `startSharedConnection()`

    - #### stop

          public void stop()
                    throws JmsException

      Stop this container.
      Specified by:
        `stop` in interface `Lifecycle`
      Throws:
        `JmsException` - if stopping failed
      See Also:
        `doStop()`

    - #### stop

          public void stop(Runnable callback)

      Description copied from interface: `SmartLifecycle`
      Indicates that a Lifecycle component must stop if it is currently running.

      The provided callback is used by the `LifecycleProcessor` to support an ordered, and potentially concurrent, shutdown of all components having a common shutdown order value. The callback must be executed after the SmartLifecycle component does indeed stop.

      The `LifecycleProcessor` will call only this variant of the `stop` method; i.e. `Lifecycle.stop()` will not be called for `SmartLifecycle` implementations unless explicitly delegated to within this method.

      Specified by:
        `stop` in interface `SmartLifecycle`

    - #### doStop

          protected void doStop()
                         throws JMSException

      Notify all invoker tasks and stop the shared Connection, if any.
      Throws:
        `JMSException` - if thrown by JMS API methods
      See Also:
        `stopSharedConnection()`

    - #### isRunning

          public final boolean isRunning()

      Determine whether this container is currently running, that is, whether it has been started and not stopped yet.
      Specified by:
        `isRunning` in interface `Lifecycle`
      Returns:
        whether the component is currently running
      See Also:
        `start()`, `stop()`, `runningAllowed()`

    - #### runningAllowed

          protected boolean runningAllowed()

      Check whether this container's listeners are generally allowed to run.

      This implementation always returns `true`; the default 'running' state is purely determined by `start()` / `stop()`.

      Subclasses may override this method to check against temporary conditions that prevent listeners from actually running. In other words, they may apply further restrictions to the 'running' state, returning `false` if such a restriction prevents listeners from running.

    - #### establishSharedConnection

          protected void establishSharedConnection()
                                            throws JMSException

      Establish a shared Connection for this container.

      The default implementation delegates to `createSharedConnection()`, which does one immediate attempt and throws an exception if it fails. Can be overridden to have a recovery process in place, retrying until a Connection can be successfully established.

      Throws:
        `JMSException` - if thrown by JMS API methods

    - #### refreshSharedConnection

          protected final void refreshSharedConnection()
                                                throws JMSException

      Refresh the shared Connection that this container holds.

      Called on startup and also after an infrastructure exception that occurred during invoker setup and/or execution.

      Throws:
        `JMSException` - if thrown by JMS API methods

    - #### createSharedConnection

          protected Connection createSharedConnection()
                                               throws JMSException

      Create a shared Connection for this container.

      The default implementation creates a standard Connection and prepares it through `prepareSharedConnection(javax.jms.Connection)`.

      Returns:
        the prepared Connection
      Throws:
        `JMSException` - if the creation failed

    - #### prepareSharedConnection

          protected void prepareSharedConnection(Connection connection)
                                          throws JMSException

      Prepare the given Connection, which is about to be registered as shared Connection for this container.

      The default implementation sets the specified client id, if any. Subclasses can override this to apply further settings.

      Parameters:
        `connection` - the Connection to prepare
      Throws:
        `JMSException` - if the preparation efforts failed
      See Also:
        `getClientId()`

    - #### startSharedConnection

          protected void startSharedConnection()
                                        throws JMSException

      Start the shared Connection.
      Throws:
        `JMSException` - if thrown by JMS API methods
      See Also:
        `Connection.start()`

    - #### stopSharedConnection

          protected void stopSharedConnection()
                                       throws JMSException

      Stop the shared Connection.
      Throws:
        `JMSException` - if thrown by JMS API methods
      See Also:
        `Connection.start()`

    - #### getSharedConnection

          protected final Connection getSharedConnection()

      Return the shared JMS Connection maintained by this container. Available after initialization.
      Returns:
        the shared Connection (never `null`)
      Throws:
        `IllegalStateException` - if this container does not maintain a shared Connection, or if the Connection hasn't been initialized yet
      See Also:
        `sharedConnectionEnabled()`

    - #### rescheduleTaskIfNecessary

          protected final boolean rescheduleTaskIfNecessary(Object task)

      Take the given task object and reschedule it, either immediately if this container is currently running, or later once this container has been restarted.

      If this container has already been shut down, the task will not get rescheduled at all.

      Parameters:
        `task` - the task object to reschedule
      Returns:
        whether the task has been rescheduled (either immediately or for a restart of this container)
      See Also:
        `doRescheduleTask(java.lang.Object)`

    - #### resumePausedTasks

          protected void resumePausedTasks()

      Try to resume all paused tasks. Tasks for which rescheduling failed simply remain in paused mode.

    - #### getPausedTaskCount

          public int getPausedTaskCount()

      Determine the number of currently paused tasks, if any.

    - #### doRescheduleTask

          protected void doRescheduleTask(Object task)

      Reschedule the given task object immediately.

      To be implemented by subclasses if they ever call `rescheduleTaskIfNecessary`. This implementation throws an UnsupportedOperationException.

      Parameters:
        `task` - the task object to reschedule
      See Also:
        `rescheduleTaskIfNecessary(java.lang.Object)`

    - #### logRejectedTask

          protected void logRejectedTask(Object task,
                             RuntimeException ex)

      Log a task that has been rejected by `doRescheduleTask(java.lang.Object)`.

      The default implementation simply logs a corresponding message at debug level.

      Parameters:
        `task` - the rejected task object
        `ex` - the exception thrown from `doRescheduleTask(java.lang.Object)`

    - #### sharedConnectionEnabled

          protected abstract boolean sharedConnectionEnabled()

      Return whether a shared JMS Connection should be maintained by this container base class.
      See Also:
        `getSharedConnection()`

    - #### doInitialize

          protected abstract void doInitialize()
                                        throws JMSException

      Register any invokers within this container.

      Subclasses need to implement this method for their specific invoker management process.

      A shared JMS Connection, if any, will already have been started at this point.

      Throws:
        `JMSException` - if registration failed
      See Also:
        `getSharedConnection()`

    - #### doShutdown

          protected abstract void doShutdown()
                                      throws JMSException

      Close the registered invokers.

      Subclasses need to implement this method for their specific invoker management process.

      A shared JMS Connection, if any, will automatically be closed afterwards.

      Throws:
        `JMSException` - if shutdown failed
      See Also:
        `shutdown()`