Spring boot Spring JMS事务回滚-消息从ActiveMQ退出队列
我有一个简单的Spring引导应用程序(Spring引导版本1.5.3.RELEASE),用于从ActiveMQ(版本5.14.5)队列中使用JMS消息 我希望消息在JMS事务中使用。若在消息使用过程中出现异常,我希望事务回滚,消息不会退出队列(从消息队列中取出)。我可以在Spring日志中看到事务被回滚,但是消息仍然从ActiveMQ队列中退出队列(在六次重新传递尝试之后) 任何指点都将不胜感激 以下是应用程序代码:Spring boot Spring JMS事务回滚-消息从ActiveMQ退出队列,spring-boot,activemq,spring-transactions,spring-jms,Spring Boot,Activemq,Spring Transactions,Spring Jms,我有一个简单的Spring引导应用程序(Spring引导版本1.5.3.RELEASE),用于从ActiveMQ(版本5.14.5)队列中使用JMS消息 我希望消息在JMS事务中使用。若在消息使用过程中出现异常,我希望事务回滚,消息不会退出队列(从消息队列中取出)。我可以在Spring日志中看到事务被回滚,但是消息仍然从ActiveMQ队列中退出队列(在六次重新传递尝试之后) 任何指点都将不胜感激 以下是应用程序代码: @SpringBootApplication public class S
@SpringBootApplication
public class SpringJmsDemoApplication {
public static void main(String[] args) {
SpringApplication.run(SpringJmsDemoApplication.class, args);
}
@Bean
public JmsListenerContainerFactory<?> myFactory(ConnectionFactory connectionFactory,
DefaultJmsListenerContainerFactoryConfigurer configurer) {
DefaultJmsListenerContainerFactory defaultJmsListenerContainerFactory = new DefaultJmsListenerContainerFactory();
defaultJmsListenerContainerFactory.setTransactionManager(jmsTransactionManager(connectionFactory));
defaultJmsListenerContainerFactory.setSessionTransacted(true);
defaultJmsListenerContainerFactory.setSessionAcknowledgeMode(Session.SESSION_TRANSACTED);
configurer.configure(defaultJmsListenerContainerFactory, connectionFactory);
return defaultJmsListenerContainerFactory;
}
@Bean
public PlatformTransactionManager jmsTransactionManager(ConnectionFactory connectionFactory) {
return new JmsTransactionManager(connectionFactory);
}
}
@Component
根据ActiveMQ消息重新传递文档,未能传递的消息将进入死信队列(): “ActiveMQ中的默认死信队列称为ActiveMQ.DLQ;所有不可交付的消息都将发送到此队列,这可能很难管理。因此,您可以在
activemq.xml
配置文件的目标策略映射中设置individualDeadLetterStrategy
,它允许您为给定队列或主题指定特定的死信队列前缀。如果愿意,您可以使用通配符应用此策略,以便所有队列都有自己的死信队列,如下例所示“
请使用
individualDeadLetterStrategy
将您的activemq.xml
扩展到队列中。这似乎是activemq的一个功能,在消息的重新传递尝试和事务回滚失败后,消息中的消息被移动到默认的死信队列中。我检查了activemq代理日志,可以看到代理“回滚”“返回消息,但回滚的效果是消息退出队列,而不是保持排队状态。”。我在管理控制台上看不到任何默认死信通道队列。是否可以配置ActiveMQ Broker,以便在事务回滚时,消息不会路由到死信队列,而是保持在原始队列上排队?在应用程序持久存储(db)关闭的场景中,我希望消息保持排队状态,而不是移动到交易信函队列。
@JmsListener(destination = "mailbox", containerFactory = "myFactory")
@Transactional
public void receiveMessage(String email) {
System.out.println("Received <" + email + ">");
throw new RuntimeException("nooo");
}
2017-05-24 09:51:59.865 DEBUG 8972 --- [DefaultMessageListenerContainer-1] o.s.j.connection.JmsTransactionManager : Created JMS transaction on Session [ActiveMQSession {id=ID:D6C0B8467A518-58248-1495590693980-1:32:1,started=false} java.lang.Object@65d647cd] from Connection [ActiveMQConnection
2017-05-24 09:51:59.867 DEBUG 8972 --- [DefaultMessageListenerContainer-1] o.s.j.l.DefaultMessageListenerContainer : Received message of type [class org.apache.activemq.command.ActiveMQTextMessage] from consumer [ActiveMQMessageConsumer { value=ID:D6C0B8467A518-58248-1495590693980-1:32:1:1, started=true }] of transactional session [ActiveMQSession {id=ID:D6C0B8467A518-58248-1495590693980-1:32:1,started=true} java.lang.Object@65d647cd]
2017-05-24 09:51:59.867 DEBUG 8972 --- [DefaultMessageListenerContainer-1] o.s.j.l.DefaultMessageListenerContainer : Rolling back transaction because of listener exception thrown: org.springframework.jms.listener.adapter.ListenerExecutionFailedException: Listener method 'public void com.anz.markets.springjmsdemo.Receiver.receiveMessage(java.lang.String)' threw exception; nested exception is java.lang.RuntimeException: nooo
2017-05-24 09:51:59.867 WARN 8972 --- [DefaultMessageListenerContainer-1] o.s.j.l.DefaultMessageListenerContainer : Execution of JMS message listener failed, and no ErrorHandler has been set.
org.springframework.jms.listener.adapter.ListenerExecutionFailedException: Listener method 'public void com.anz.markets.springjmsdemo.Receiver.receiveMessage(java.lang.String)' threw exception; nested exception is java.lang.RuntimeException: nooo
at org.springframework.jms.listener.adapter.MessagingMessageListenerAdapter.invokeHandler(MessagingMessageListenerAdapter.java:112) ~[spring-jms-4.3.8.RELEASE.jar:4.3.8.RELEASE]
at org.springframework.jms.listener.adapter.MessagingMessageListenerAdapter.onMessage(MessagingMessageListenerAdapter.java:69) ~[spring-jms-4.3.8.RELEASE.jar:4.3.8.RELEASE]
at org.springframework.jms.listener.AbstractMessageListenerContainer.doInvokeListener(AbstractMessageListenerContainer.java:721) ~[spring-jms-4.3.8.RELEASE.jar:4.3.8.RELEASE]
at org.springframework.jms.listener.AbstractMessageListenerContainer.invokeListener(AbstractMessageListenerContainer.java:681) ~[spring-jms-4.3.8.RELEASE.jar:4.3.8.RELEASE]
at org.springframework.jms.listener.AbstractMessageListenerContainer.doExecuteListener(AbstractMessageListenerContainer.java:651) ~[spring-jms-4.3.8.RELEASE.jar:4.3.8.RELEASE]
at org.springframework.jms.listener.AbstractPollingMessageListenerContainer.doReceiveAndExecute(AbstractPollingMessageListenerContainer.java:317) [spring-jms-4.3.8.RELEASE.jar:4.3.8.RELEASE]
at org.springframework.jms.listener.AbstractPollingMessageListenerContainer.receiveAndExecute(AbstractPollingMessageListenerContainer.java:235) [spring-jms-4.3.8.RELEASE.jar:4.3.8.RELEASE]
at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.invokeListener(DefaultMessageListenerContainer.java:1166) [spring-jms-4.3.8.RELEASE.jar:4.3.8.RELEASE]
at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.executeOngoingLoop(DefaultMessageListenerContainer.java:1158) [spring-jms-4.3.8.RELEASE.jar:4.3.8.RELEASE]
at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.run(DefaultMessageListenerContainer.java:1055) [spring-jms-4.3.8.RELEASE.jar:4.3.8.RELEASE]
at java.lang.Thread.run(Thread.java:745) [na:1.8.0_72]
Caused by: java.lang.RuntimeException: nooo
at com.anz.markets.springjmsdemo.Receiver.receiveMessage(Receiver.java:12) ~[classes/:na]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_72]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_72]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_72]
at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_72]
at org.springframework.messaging.handler.invocation.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:180) ~[spring-messaging-4.3.8.RELEASE.jar:4.3.8.RELEASE]
at org.springframework.messaging.handler.invocation.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:112) ~[spring-messaging-4.3.8.RELEASE.jar:4.3.8.RELEASE]
at org.springframework.jms.listener.adapter.MessagingMessageListenerAdapter.invokeHandler(MessagingMessageListenerAdapter.java:104) ~[spring-jms-4.3.8.RELEASE.jar:4.3.8.RELEASE]
... 10 common frames omitted
2017-05-24 09:51:59.868 DEBUG 8972 --- [DefaultMessageListenerContainer-1] o.s.j.connection.JmsTransactionManager : Transactional code has requested rollback
2017-05-24 09:51:59.868 DEBUG 8972 --- [DefaultMessageListenerContainer-1] o.s.j.connection.JmsTransactionManager : Initiating transaction rollback
2017-05-24 09:51:59.868 DEBUG 8972 --- [DefaultMessageListenerContainer-1] o.s.j.connection.JmsTransactionManager : Rolling back JMS transaction on Session [ActiveMQSession {id=ID:D6C0B8467A518-58248-1495590693980-1:32:1,started=true} java.lang.Object@65d647cd]