| org.springframework.jms.listener.AbstractJmsListeningContainer org.springframework.jms.listener.AbstractMessageListenerContainer
All known Subclasses: org.springframework.jms.listener.serversession.ServerSessionMessageListenerContainer, org.springframework.jms.listener.AbstractPollingMessageListenerContainer, org.springframework.jms.listener.SimpleMessageListenerContainer,
AbstractMessageListenerContainer | abstract public class AbstractMessageListenerContainer extends AbstractJmsListeningContainer (Code) | | Abstract base class for message listener containers. Can either host
a standard JMS
javax.jms.MessageListener or a Spring-specific
SessionAwareMessageListener .
Usually holds a single JMS
Connection that all listeners are
supposed to be registered on, which is the standard JMS way of managing
listeners. Can alternatively also be used with a fresh Connection per
listener, for J2EE-style XA-aware JMS messaging. The actual registration
process is up to concrete subclasses.
NOTE: The default behavior of this message listener container
is to never propagate an exception thrown by a message listener up to
the JMS provider. Instead, it will log any such exception at the error level.
This means that from the perspective of the attendant JMS provider no such
listener will ever fail.
The listener container offers the following message acknowledgment options:
- "sessionAcknowledgeMode" set to "AUTO_ACKNOWLEDGE" (default):
Automatic message acknowledgment before listener execution;
no redelivery in case of exception thrown.
- "sessionAcknowledgeMode" set to "CLIENT_ACKNOWLEDGE":
Automatic message acknowledgment after successful listener execution;
no redelivery in case of exception thrown.
- "sessionAcknowledgeMode" set to "DUPS_OK_ACKNOWLEDGE":
Lazy message acknowledgment during or after listener execution;
potential redelivery in case of exception thrown.
- "sessionTransacted" set to "true":
Transactional acknowledgment after successful listener execution;
guaranteed redelivery in case of exception thrown.
The exact behavior might vary according to the concrete listener container
and JMS provider used.
NOTE: The default behavior of this message listener container is to
never propagate an exception thrown by a message listener up to the
JMS provider. Instead, it will log any such exception at the error level and
rollback the active transaction if there is one. This means that from the
perspective of the attendant JMS provider no listener will ever fail.
There are two solutions to the duplicate processing problem:
- Either add duplicate message detection to your listener, in the
form of a business entity existence check or a protocol table check. This
usually just needs to be done in case of the JMSRedelivered flag being
set on the incoming message (else just process straightforwardly).
- Or wrap the entire processing with an XA transaction, covering the
reception of the message as well as the execution of the message listener.
This is only supported by
DefaultMessageListenerContainer , through
specifying a "transactionManager" (typically a
org.springframework.transaction.jta.JtaTransactionManager , with
a corresponding XA-aware JMS
javax.jms.ConnectionFactory passed in as
"connectionFactory").
Note that XA transaction coordination adds significant runtime overhead,
so it might be feasible to avoid it unless absolutely necessary.
Recommendations:
- The general recommendation is to set "sessionTransacted" to "true",
typically in combination with local database transactions triggered by the
listener implementation, through Spring's standard transaction facilities.
This will work nicely in Tomcat or in a standalone environment, often
combined with custom duplicate message detection (if it is unacceptable
to ever process the same message twice).
- Alternatively, specify a
org.springframework.transaction.jta.JtaTransactionManager as
"transactionManager" for a fully XA-aware JMS provider - typically when
running on a J2EE server, but also for other environments with a JTA
transaction manager present. This will give full "exactly-once" guarantees
without custom duplicate message checks, at the price of additional
runtime processing overhead.
Note that it is also possible to specify a
org.springframework.jms.connection.JmsTransactionManager as external
"transactionManager", providing fully synchronized Spring transactions based
on local JMS transactions. The effect is similar to "sessionTransacted" set
to "true", the difference being that this external transaction management
will also affect independent JMS access code within the service layer
(e.g. based on
org.springframework.jms.core.JmsTemplate or
org.springframework.jms.connection.TransactionAwareConnectionFactoryProxy ),
not just direct JMS Session usage in a
SessionAwareMessageListener .
author: Juergen Hoeller since: 2.0 See Also: AbstractMessageListenerContainer.setMessageListener See Also: javax.jms.MessageListener See Also: SessionAwareMessageListener See Also: AbstractMessageListenerContainer.handleListenerException See Also: DefaultMessageListenerContainer See Also: SimpleMessageListenerContainer See Also: org.springframework.jms.listener.serversession.ServerSessionMessageListenerContainer |
Method Summary | |
protected void | checkMessageListener(Object messageListener) Check the given message listener, throwing an exception
if it does not correspond to a supported listener type. | protected void | commitIfNecessary(Session session, Message message) Perform a commit or message acknowledgement, as appropriate. | protected void | doExecuteListener(Session session, Message message) Execute the specified listener,
committing or rolling back the transaction afterwards (if necessary). | protected void | doInvokeListener(SessionAwareMessageListener listener, Session session, Message message) Invoke the specified listener as Spring SessionAwareMessageListener,
exposing a new JMS Session (potentially with its own transaction)
to the listener if demanded. | protected void | doInvokeListener(MessageListener listener, Message message) Invoke the specified listener as standard JMS MessageListener. | protected void | executeListener(Session session, Message message) Execute the specified listener,
committing or rolling back the transaction afterwards (if necessary). | public Destination | getDestination() Return the destination to receive messages from. | public String | getDestinationName() Return the name of the destination to receive messages from.
Will be null if the configured destination is not a
String type; c.f. | public String | getDurableSubscriptionName() Return the name of a durable subscription to create, if any. | public ExceptionListener | getExceptionListener() Return the JMS ExceptionListener to notify in case of a JMSException thrown
by the registered message listener or the invocation infrastructure, if any. | public Object | getMessageListener() Return the message listener object to register. | public String | getMessageSelector() Return the JMS message selector expression (or null if none). | protected void | handleListenerException(Throwable ex) Handle the given exception that arose during listener execution. | protected void | invokeExceptionListener(JMSException ex) Invoke the registered JMS ExceptionListener, if any. | protected void | invokeListener(Session session, Message message) Invoke the specified listener: either as standard JMS MessageListener
or (preferably) as Spring SessionAwareMessageListener. | public boolean | isAcceptMessagesWhileStopping() Return whether to accept received messages while the listener container
in the process of stopping. | public boolean | isExposeListenerSession() Return whether to expose the listener JMS
Session to a
registered
SessionAwareMessageListener . | protected boolean | isSessionLocallyTransacted(Session session) Check whether the given Session is locally transacted, that is, whether
its transaction is managed by this listener container's Session handling
and not by an external transaction coordinator.
Note: The Session's own transacted flag will already have been checked
before. | public boolean | isSubscriptionDurable() Return whether to make the subscription durable. | protected void | rollbackIfNecessary(Session session) Perform a rollback, if appropriate. | protected void | rollbackOnExceptionIfNecessary(Session session, Throwable ex) Perform a rollback, handling rollback exceptions properly. | public void | setAcceptMessagesWhileStopping(boolean acceptMessagesWhileStopping) Set whether to accept received messages while the listener container
in the process of stopping.
Default is "false", rejecting such messages through aborting the
receive attempt. | public void | setDestination(Destination destination) Set the destination to receive messages from. | public void | setDestinationName(String destinationName) Set the name of the destination to receive messages from. | public void | setDurableSubscriptionName(String durableSubscriptionName) Set the name of a durable subscription to create. | public void | setExceptionListener(ExceptionListener exceptionListener) Set the JMS ExceptionListener to notify in case of a JMSException thrown
by the registered message listener or the invocation infrastructure. | public void | setExposeListenerSession(boolean exposeListenerSession) Set whether to expose the listener JMS Session to a registered
SessionAwareMessageListener . | public void | setMessageListener(Object messageListener) Set the message listener implementation to register. | public void | setMessageSelector(String messageSelector) Set the JMS message selector expression (or null if none). | public void | setSubscriptionDurable(boolean subscriptionDurable) Set whether to make the subscription durable. | protected void | validateConfiguration() |
commitIfNecessary | protected void commitIfNecessary(Session session, Message message) throws JMSException(Code) | | Perform a commit or message acknowledgement, as appropriate.
Parameters: session - the JMS Session to commit Parameters: message - the Message to acknowledge throws: javax.jms.JMSException - in case of commit failure |
doInvokeListener | protected void doInvokeListener(SessionAwareMessageListener listener, Session session, Message message) throws JMSException(Code) | | Invoke the specified listener as Spring SessionAwareMessageListener,
exposing a new JMS Session (potentially with its own transaction)
to the listener if demanded.
Parameters: listener - the Spring SessionAwareMessageListener to invoke Parameters: session - the JMS Session to operate on Parameters: message - the received JMS Message throws: JMSException - if thrown by JMS API methods See Also: SessionAwareMessageListener See Also: AbstractMessageListenerContainer.setExposeListenerSession |
doInvokeListener | protected void doInvokeListener(MessageListener listener, Message message) throws JMSException(Code) | | Invoke the specified listener as standard JMS MessageListener.
Default implementation performs a plain invocation of the
onMessage method.
Parameters: listener - the JMS MessageListener to invoke Parameters: message - the received JMS Message throws: JMSException - if thrown by JMS API methods See Also: javax.jms.MessageListener.onMessage |
getDurableSubscriptionName | public String getDurableSubscriptionName()(Code) | | Return the name of a durable subscription to create, if any.
|
getExceptionListener | public ExceptionListener getExceptionListener()(Code) | | Return the JMS ExceptionListener to notify in case of a JMSException thrown
by the registered message listener or the invocation infrastructure, if any.
|
getMessageListener | public Object getMessageListener()(Code) | | Return the message listener object to register.
|
getMessageSelector | public String getMessageSelector()(Code) | | Return the JMS message selector expression (or null if none).
|
handleListenerException | protected void handleListenerException(Throwable ex)(Code) | | Handle the given exception that arose during listener execution.
The default implementation logs the exception at error level,
not propagating it to the JMS provider - assuming that all handling of
acknowledgement and/or transactions is done by this listener container.
This can be overridden in subclasses.
Parameters: ex - the exception to handle |
invokeListener | protected void invokeListener(Session session, Message message) throws JMSException(Code) | | Invoke the specified listener: either as standard JMS MessageListener
or (preferably) as Spring SessionAwareMessageListener.
Parameters: session - the JMS Session to operate on Parameters: message - the received JMS Message throws: JMSException - if thrown by JMS API methods See Also: AbstractMessageListenerContainer.setMessageListener |
isAcceptMessagesWhileStopping | public boolean isAcceptMessagesWhileStopping()(Code) | | Return whether to accept received messages while the listener container
in the process of stopping.
|
isExposeListenerSession | public boolean isExposeListenerSession()(Code) | | Return whether to expose the listener JMS
Session to a
registered
SessionAwareMessageListener .
|
isSessionLocallyTransacted | protected boolean isSessionLocallyTransacted(Session session)(Code) | | Check whether the given Session is locally transacted, that is, whether
its transaction is managed by this listener container's Session handling
and not by an external transaction coordinator.
Note: The Session's own transacted flag will already have been checked
before. This method is about finding out whether the Session's transaction
is local or externally coordinated.
Parameters: session - the Session to check whether the given Session is locally transacted See Also: AbstractMessageListenerContainer.isSessionTransacted() See Also: org.springframework.jms.connection.ConnectionFactoryUtils.isSessionTransactional |
isSubscriptionDurable | public boolean isSubscriptionDurable()(Code) | | Return whether to make the subscription durable.
|
rollbackIfNecessary | protected void rollbackIfNecessary(Session session) throws JMSException(Code) | | Perform a rollback, if appropriate.
Parameters: session - the JMS Session to rollback throws: javax.jms.JMSException - in case of a rollback error |
rollbackOnExceptionIfNecessary | protected void rollbackOnExceptionIfNecessary(Session session, Throwable ex) throws JMSException(Code) | | Perform a rollback, handling rollback exceptions properly.
Parameters: session - the JMS Session to rollback Parameters: ex - the thrown application exception or error throws: javax.jms.JMSException - in case of a rollback error |
setAcceptMessagesWhileStopping | public void setAcceptMessagesWhileStopping(boolean acceptMessagesWhileStopping)(Code) | | Set whether to accept received messages while the listener container
in the process of stopping.
Default is "false", rejecting such messages through aborting the
receive attempt. Switch this flag on to fully process such messages
even in the stopping phase, with the drawback that even newly sent
messages might still get processed (if coming in before all receive
timeouts have expired).
NOTE: Aborting receive attempts for such incoming messages
might lead to the provider's retry count decreasing for the affected
messages. If you have a high number of concurrent consumers, make sure
that the number of retries is higher than the number of consumers,
to be on the safe side for all potential stopping scenarios.
|
setExceptionListener | public void setExceptionListener(ExceptionListener exceptionListener)(Code) | | Set the JMS ExceptionListener to notify in case of a JMSException thrown
by the registered message listener or the invocation infrastructure.
|
setExposeListenerSession | public void setExposeListenerSession(boolean exposeListenerSession)(Code) | | Set whether to expose the listener JMS Session to a registered
SessionAwareMessageListener . Default is "true", reusing
the listener's
Session .
Turn this off to expose a fresh JMS Session fetched from the same
underlying JMS
Connection instead, which might be necessary
on some JMS providers.
See Also: SessionAwareMessageListener |
setMessageSelector | public void setMessageSelector(String messageSelector)(Code) | | Set the JMS message selector expression (or null if none).
Default is none.
See the JMS specification for a detailed definition of selector expressions.
|
setSubscriptionDurable | public void setSubscriptionDurable(boolean subscriptionDurable)(Code) | | Set whether to make the subscription durable. The durable subscription name
to be used can be specified through the "durableSubscriptionName" property.
Default is "false". Set this to "true" to register a durable subscription,
typically in combination with a "durableSubscriptionName" value (unless
your message listener class name is good enough as subscription name).
Only makes sense when listening to a topic (pub-sub domain).
See Also: AbstractMessageListenerContainer.setDurableSubscriptionName |
validateConfiguration | protected void validateConfiguration()(Code) | | |
|
|