问题
I am trying to understand how acknowledgement modes work in JMS. I was reading this source and it hugely confused me as it was contradicting what Spring's documentation says.
Sources saying one thing: From http://www.javaworld.com/article/2074123/java-web-development/transaction-and-redelivery-in-jms.html
A message is automatically acknowledged when it successfully returns from the receive() method. If the receiver uses the MessageListener interface, the message is automatically acknowledged when it successfully returns from the onMessage() method. If a failure occurs while executing the receive() method or the onMessage() method, the message is automatically redelivered.
From http://www2.sys-con.com/itsg/virtualcd/Java/archives/0604/chappell/index.html
With AUTO_ACKNOWLEDGE mode the acknowledgment is always the last thing to happen implicitly after the onMessage() handler returns. The client receiving the messages can get finer-grained control over the delivery of guaranteed messages by specifying the CLIENT_ACKNOWLEDGE mode on the consuming session.
Spring Docs saying other things: From http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/jms/listener/AbstractMessageListenerContainer.html
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.
What I want to know is that why these sources are saying different things? If all are true then How do I know how/when my message will be acknowledged?
回答1:
You missed out the key phrase from the abstract container javadocs...
The exact behavior might vary according to the concrete listener container and JMS provider used.
The most commonly used listener container used in Spring
is the DefaultMessageListenerContainer
which does exhibit that behavior - it is intended for use with transactions (either local or an external transaction manager), in order to have the ability to roll back an already acknowledged message. Its listener is invoked after the receive method, so the standard JMS auto-ack has already been applied. Any JmsTemplate
operations on the thread can also use the same session - and thus can be part of the transaction.
On the other hand, the SimpleMessageListenerContainer
uses a traditional MessageListener
and exhibits the standard JMS behavior (the listener is called from the Consumer
before receive()
returns; thus exceptions will stop the ack).
I suggest you read the javadocs for those concrete implementations. From the SMLC
...
This is the simplest form of a message listener container. It creates a fixed
number of JMS Sessions to invoke the listener, not allowing for dynamic
adaptation to runtime demands. Its main advantage is its low level of
complexity and the minimum requirements on the JMS provider: Not even the
ServerSessionPool facility is required.
See the AbstractMessageListenerContainer javadoc for details on acknowledge
modes and transaction options.
For a different style of MessageListener handling, through looped
MessageConsumer.receive() calls that also allow for transactional reception of
messages (registering them with XA transactions), see
DefaultMessageListenerContainer.
I will open up a JIRA issue for the docs on the abstract container because I can see that it might be misleading.
来源:https://stackoverflow.com/questions/28426467/difference-between-auto-acknowledgement-mode-with-and-without-spring-jms