Explicit documentation notes on transacted sessions vs AUTO_ACKNOWLEDGE
Issue: SPR-16487
This commit is contained in:
parent
3b810f3544
commit
95f7180298
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2016 the original author or authors.
|
* Copyright 2002-2018 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -41,6 +41,7 @@ import org.springframework.context.annotation.Import;
|
||||||
* DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
|
* DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
|
||||||
* factory.setConnectionFactory(connectionFactory());
|
* factory.setConnectionFactory(connectionFactory());
|
||||||
* factory.setDestinationResolver(destinationResolver());
|
* factory.setDestinationResolver(destinationResolver());
|
||||||
|
* factory.setSessionTransacted(true);
|
||||||
* factory.setConcurrency("5");
|
* factory.setConcurrency("5");
|
||||||
* return factory;
|
* return factory;
|
||||||
* }
|
* }
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2016 the original author or authors.
|
* Copyright 2002-2018 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -33,6 +33,12 @@ import org.springframework.messaging.handler.annotation.MessageMapping;
|
||||||
* assumed to be available with a bean name of {@code jmsListenerContainerFactory}
|
* assumed to be available with a bean name of {@code jmsListenerContainerFactory}
|
||||||
* unless an explicit default has been provided through configuration.
|
* unless an explicit default has been provided through configuration.
|
||||||
*
|
*
|
||||||
|
* <p><b>Consider setting up a custom
|
||||||
|
* {@link org.springframework.jms.config.DefaultJmsListenerContainerFactory} bean.</b>
|
||||||
|
* For production purposes, you'll typically fine-tune timeouts and recovery settings.
|
||||||
|
* Most importantly, the default 'AUTO_ACKNOWLEDGE' mode does not provide reliability
|
||||||
|
* guarantees, so make sure to use transacted sessions in case of reliability needs.
|
||||||
|
*
|
||||||
* <p>Processing of {@code @JmsListener} annotations is performed by registering a
|
* <p>Processing of {@code @JmsListener} annotations is performed by registering a
|
||||||
* {@link JmsListenerAnnotationBeanPostProcessor}. This can be done manually or,
|
* {@link JmsListenerAnnotationBeanPostProcessor}. This can be done manually or,
|
||||||
* more conveniently, through the {@code <jms:annotation-driven/>} element or
|
* more conveniently, through the {@code <jms:annotation-driven/>} element or
|
||||||
|
|
|
||||||
|
|
@ -1797,6 +1797,13 @@ the message getting redelivered. Alternatively, consider using 'CLIENT_ACKNOWLED
|
||||||
which provides redelivery in case of an exception as well but does not use transacted
|
which provides redelivery in case of an exception as well but does not use transacted
|
||||||
Sessions and therefore does not include any other Session operations (such as sending
|
Sessions and therefore does not include any other Session operations (such as sending
|
||||||
response messages) in the transaction protocol.
|
response messages) in the transaction protocol.
|
||||||
|
|
||||||
|
**The default 'AUTO_ACKNOWLEDGE' mode does not provide proper reliability guarantees.**
|
||||||
|
Messages may get lost when listener execution fails (since the provider will automatically
|
||||||
|
acknowledge each message after listener invocation, with no exceptions to be propagated to
|
||||||
|
the provider) or when the listener container shuts down (this may be configured through
|
||||||
|
the 'acceptMessagesWhileStopping' flag). Make sure to use transacted sessions in case of
|
||||||
|
reliability needs, e.g. for reliable queue handling and durable topic subscriptions.
|
||||||
====
|
====
|
||||||
|
|
||||||
[[jms-mdp-default]]
|
[[jms-mdp-default]]
|
||||||
|
|
@ -1834,6 +1841,13 @@ alternative: wrapping your entire processing with an XA transaction (through con
|
||||||
your `DefaultMessageListenerContainer` with an `JtaTransactionManager`), covering the
|
your `DefaultMessageListenerContainer` with an `JtaTransactionManager`), covering the
|
||||||
reception of the JMS message as well as the execution of the business logic in your
|
reception of the JMS message as well as the execution of the business logic in your
|
||||||
message listener (including database operations etc).
|
message listener (including database operations etc).
|
||||||
|
|
||||||
|
**The default 'AUTO_ACKNOWLEDGE' mode does not provide proper reliability guarantees.**
|
||||||
|
Messages may get lost when listener execution fails (since the provider will automatically
|
||||||
|
acknowledge each message before listener invocation) or when the listener container shuts
|
||||||
|
down (this may be configured through the 'acceptMessagesWhileStopping' flag). Make sure
|
||||||
|
to use transacted sessions in case of reliability needs, e.g. for reliable queue handling
|
||||||
|
and durable topic subscriptions.
|
||||||
====
|
====
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -2065,7 +2079,6 @@ Below is a simple implementation of an MDP:
|
||||||
throw new IllegalArgumentException("Message must be of type TextMessage");
|
throw new IllegalArgumentException("Message must be of type TextMessage");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
----
|
----
|
||||||
|
|
||||||
|
|
@ -2108,7 +2121,6 @@ handling method with access to the JMS `Session` from which the `Message` was re
|
||||||
public interface SessionAwareMessageListener {
|
public interface SessionAwareMessageListener {
|
||||||
|
|
||||||
void onMessage(Message message, Session session) throws JMSException;
|
void onMessage(Message message, Session session) throws JMSException;
|
||||||
|
|
||||||
}
|
}
|
||||||
----
|
----
|
||||||
|
|
||||||
|
|
@ -2153,7 +2165,6 @@ various `Message` types that they can receive and handle.
|
||||||
void handleMessage(byte[] message);
|
void handleMessage(byte[] message);
|
||||||
|
|
||||||
void handleMessage(Serializable message);
|
void handleMessage(Serializable message);
|
||||||
|
|
||||||
}
|
}
|
||||||
----
|
----
|
||||||
|
|
||||||
|
|
@ -2200,7 +2211,6 @@ also how the `'receive(..)'` method is strongly typed to receive and respond onl
|
||||||
public interface TextMessageDelegate {
|
public interface TextMessageDelegate {
|
||||||
|
|
||||||
void receive(TextMessage message);
|
void receive(TextMessage message);
|
||||||
|
|
||||||
}
|
}
|
||||||
----
|
----
|
||||||
|
|
||||||
|
|
@ -2242,7 +2252,6 @@ non-void value. Consider the interface and class:
|
||||||
|
|
||||||
// notice the return type...
|
// notice the return type...
|
||||||
String receive(TextMessage message);
|
String receive(TextMessage message);
|
||||||
|
|
||||||
}
|
}
|
||||||
----
|
----
|
||||||
|
|
||||||
|
|
@ -2469,10 +2478,10 @@ your `@Configuration` classes.
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
public DefaultJmsListenerContainerFactory jmsListenerContainerFactory() {
|
public DefaultJmsListenerContainerFactory jmsListenerContainerFactory() {
|
||||||
DefaultJmsListenerContainerFactory factory =
|
DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
|
||||||
new DefaultJmsListenerContainerFactory();
|
|
||||||
factory.setConnectionFactory(connectionFactory());
|
factory.setConnectionFactory(connectionFactory());
|
||||||
factory.setDestinationResolver(destinationResolver());
|
factory.setDestinationResolver(destinationResolver());
|
||||||
|
factory.setSessionTransacted(true);
|
||||||
factory.setConcurrency("3-10");
|
factory.setConcurrency("3-10");
|
||||||
return factory;
|
return factory;
|
||||||
}
|
}
|
||||||
|
|
@ -2501,6 +2510,7 @@ element.
|
||||||
class="org.springframework.jms.config.DefaultJmsListenerContainerFactory">
|
class="org.springframework.jms.config.DefaultJmsListenerContainerFactory">
|
||||||
<property name="connectionFactory" ref="connectionFactory"/>
|
<property name="connectionFactory" ref="connectionFactory"/>
|
||||||
<property name="destinationResolver" ref="destinationResolver"/>
|
<property name="destinationResolver" ref="destinationResolver"/>
|
||||||
|
<property name="sessionTransacted" value="true"/>
|
||||||
<property name="concurrency" value="3-10"/>
|
<property name="concurrency" value="3-10"/>
|
||||||
</bean>
|
</bean>
|
||||||
----
|
----
|
||||||
|
|
@ -2696,8 +2706,7 @@ the time to live, you can configure the `JmsListenerContainerFactory` accordingl
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
public DefaultJmsListenerContainerFactory jmsListenerContainerFactory() {
|
public DefaultJmsListenerContainerFactory jmsListenerContainerFactory() {
|
||||||
DefaultJmsListenerContainerFactory factory =
|
DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
|
||||||
new DefaultJmsListenerContainerFactory();
|
|
||||||
factory.setConnectionFactory(connectionFactory());
|
factory.setConnectionFactory(connectionFactory());
|
||||||
QosSettings replyQosSettings = new ReplyQosSettings();
|
QosSettings replyQosSettings = new ReplyQosSettings();
|
||||||
replyQosSettings.setPriority(2);
|
replyQosSettings.setPriority(2);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue